> ## Documentation Index
> Fetch the complete documentation index at: https://docs.knoxcall.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Method-Specific Route Configuration

> Configure different headers, body templates, and secrets for each HTTP method (GET, POST, PUT, DELETE, etc.)

# Method-Specific Route Configuration

Configure different headers, body templates, and security settings for each HTTP method on a single route.

## What are Method Configs?

**Method configs** let you customize route behavior per HTTP method. For example:

* **GET requests**: Inject read-only API key
* **POST requests**: Inject write API key + additional auth
* **DELETE requests**: Require admin API key + signature

All on the **same route** with **same URL**!

## Why Use Method Configs?

### Use Case 1: Different API Keys Per Method

Your API uses different keys for read vs write operations:

```text theme={"dark"}
GET /api/users → Read-only key (safe)
POST /api/users → Write key (more powerful)
DELETE /api/users → Admin key (most powerful)
```

### Use Case 2: Method-Specific Headers

```text theme={"dark"}
GET → No special headers
POST → Add "X-Idempotency-Key" header
PUT → Add "X-If-Match" header for concurrency
```

### Use Case 3: Different Secrets Per Method

```text theme={"dark"}
GET → Use caching credentials
POST → Use write credentials + webhook secret
```

### Use Case 4: Security Levels

```text theme={"dark"}
GET → No signature required (public reads)
POST/PUT/DELETE → Require HMAC signature (mutations)
```

## How It Works

### Fallback System

```text theme={"dark"}
1. Check: Does this HTTP method have a method config?
   ↓ YES
   Use method-specific config
   ↓ NO
   Use global route config (fallback)
```

**Example:**

```text theme={"dark"}
Route global config:
  inject_headers: {"Authorization": "Bearer {{secret:read_key}}"}

POST method config:
  inject_headers: {"Authorization": "Bearer {{secret:write_key}}"}

GET method config:
  (none - uses global)
```

**Result:**

* GET requests → Uses read\_key (global)
* POST requests → Uses write\_key (method config)
* PUT requests → Uses read\_key (global, no method config)

## Create Method Config

### Step 1: Edit Your Route

1. Navigate to **Routes**
2. Click your route
3. Click **Edit**

### Step 2: Scroll to Method Configs

Find the **Method-Specific Configuration** section

### Step 3: Add Method Config

Click **Add Method Config**

**Select HTTP Method:**

```text theme={"dark"}
POST
```

**Inject Headers:**

```json theme={"dark"}
{
  "Authorization": "Bearer {{secret:stripe_write_key}}",
  "X-Idempotency-Key": "{{var:idempotency_key}}"
}
```

**Inject Body:**

```json theme={"dark"}
{
  "api_key": "{{secret:stripe_write_key}}",
  "timestamp": "{{var:timestamp}}"
}
```

**Override other settings** (optional):

* Rate limit
* Require signature
* Allowed origins

### Step 4: Save

Click **Save Changes**

Now POST requests use different configuration!

## Example: Read vs Write Keys

### Scenario

You have a REST API with:

* **Read operations**: GET (low risk)
* **Write operations**: POST, PUT, DELETE (high risk)

You want different API keys for each.

### Setup

**Create secrets:**

1. `api_read_key` → sk\_read\_abc123
2. `api_write_key` → sk\_write\_xyz789

**Route global config:**

```json theme={"dark"}
{
  "inject_headers": {
    "Authorization": "Bearer {{secret:api_read_key}}"
  }
}
```

*Default: Use read-only key*

**POST method config:**

```json theme={"dark"}
{
  "inject_headers": {
    "Authorization": "Bearer {{secret:api_write_key}}"
  }
}
```

**PUT method config:**

```json theme={"dark"}
{
  "inject_headers": {
    "Authorization": "Bearer {{secret:api_write_key}}"
  }
}
```

**DELETE method config:**

```json theme={"dark"}
{
  "inject_headers": {
    "Authorization": "Bearer {{secret:api_write_key}}",
    "X-Confirm-Delete": "true"
  }
}
```

### Result

```bash theme={"dark"}
# GET → Uses read_key
curl https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api"
# Backend receives: Authorization: Bearer sk_read_abc123

# POST → Uses write_key
curl -X POST https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api" \
  -d '{"name":"John"}'
# Backend receives: Authorization: Bearer sk_write_xyz789

# DELETE → Uses write_key + confirm header
curl -X DELETE https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users/123 \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api"
# Backend receives:
#   Authorization: Bearer sk_write_xyz789
#   X-Confirm-Delete: true
```

## Example: Idempotency for POST

### Scenario

Your API requires idempotency keys for POST requests to prevent duplicate processing.

### Setup

**POST method config only:**

```json theme={"dark"}
{
  "inject_headers": {
    "Authorization": "Bearer {{secret:api_key}}",
    "X-Idempotency-Key": "{{var:idempotency_key}}"
  }
}
```

### Usage

Client includes idempotency key in query param:

```bash theme={"dark"}
curl -X POST "https://a1b2c3d4.DunderMifflin.knoxcall.com/api/charge?idempotency_key=abc-123-xyz" \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: payment-api" \
  -d '{"amount": 1000}'
```

KnoxCall extracts `idempotency_key` from query and injects as header:

```text theme={"dark"}
POST /api/charge
Authorization: Bearer sk_live_...
X-Idempotency-Key: abc-123-xyz
```

Backend receives idempotency key in header (standard pattern).

## Example: Signature Only for Mutations

### Scenario

You want to require HMAC signatures for POST/PUT/DELETE but not GET (performance).

### Setup

**Global route config:**

```text theme={"dark"}
require_signature: false
```

**POST method config:**

```text theme={"dark"}
require_signature: true
```

**PUT method config:**

```text theme={"dark"}
require_signature: true
```

**DELETE method config:**

```text theme={"dark"}
require_signature: true
```

### Result

```bash theme={"dark"}
# GET → No signature required (fast)
curl https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api"
# ✓ Works

# POST → Signature required
curl -X POST https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api" \
  -d '{"name":"John"}'
# ✗ Fails: Missing signature

# POST with signature → Works
curl -X POST https://a1b2c3d4.DunderMifflin.knoxcall.com/api/users \
  -H "x-knoxcall-key: tk_..." \
  -H "x-knoxcall-route: user-api" \
  -H "x-knoxcall-signature: t=1234567890,v1=abc123..." \
  -d '{"name":"John"}'
# ✓ Works
```

## Advanced: Method-Specific Rate Limits

### Scenario

Allow many GET requests (reads) but limit POST requests (writes).

### Setup

**Global route:**

```text theme={"dark"}
rate_limit_requests: 1000
rate_limit_window_sec: 60
```

*1000 requests per minute for GET*

**POST method config:**

```text theme={"dark"}
rate_limit_requests: 100
rate_limit_window_sec: 60
```

*Only 100 POST requests per minute*

### Result

* GET: 1000/min allowed
* POST: 100/min allowed
* Other methods: 1000/min (global)

## Variables Available in Templates

### Query Parameters: `{{var:param_name}}`

```bash theme={"dark"}
# Request
GET /api/users?filter=active&sort=name

# Template
{
  "X-Filter": "{{var:filter}}",
  "X-Sort": "{{var:sort}}"
}

# Backend receives
X-Filter: active
X-Sort: name
```

### Secrets: `{{secret:name}}`

```json theme={"dark"}
{
  "Authorization": "Bearer {{secret:api_key}}"
}
```

### Environment Variables

Can reference in templates for dynamic values.

## Viewing Method Configs

### In Route Details

1. Navigate to **Routes**
2. Click your route
3. See **Method Configs** section
4. Shows all configured methods with icons:
   * 🟢 GET
   * 🔵 POST
   * 🟡 PUT
   * 🔴 DELETE
   * ⚫ PATCH
   * 🟣 OPTIONS
   * ⚪ HEAD

### In Logs

Request logs show which config was used:

```text theme={"dark"}
Method: POST
Config Used: POST method config
Headers Injected: Authorization, X-Idempotency-Key
```

Or:

```text theme={"dark"}
Method: GET
Config Used: Global route config (no method override)
Headers Injected: Authorization
```

## Best Practices

### 1. Use Global as Default

Configure global headers/body for the most common case (usually GET).

Method configs only for exceptions.

### 2. Principle of Least Privilege

```text theme={"dark"}
GET → Read-only credentials
POST/PUT → Write credentials
DELETE → Admin credentials with confirmation
```

Give each method minimum necessary permissions.

### 3. Document Your Method Configs

Use route description to note:

```text theme={"dark"}
GET: Uses read_key (public)
POST: Uses write_key + idempotency
DELETE: Requires admin_key + signature
```

Helps team understand configuration.

### 4. Test Each Method

Don't assume method configs work without testing:

```bash theme={"dark"}
# Test GET
curl -X GET ...

# Test POST
curl -X POST ...

# Test DELETE
curl -X DELETE ...
```

Verify correct headers/body injected for each.

### 5. Monitor Per-Method Metrics

In Analytics, filter by HTTP method:

* GET success rate
* POST latency
* DELETE error rate

Identify method-specific issues.

## Common Patterns

### REST API Standard

```text theme={"dark"}
GET    → read_key
POST   → write_key
PUT    → write_key
PATCH  → write_key
DELETE → admin_key
```

### Webhook Receiver

```text theme={"dark"}
POST → Validate webhook signature
     → Inject processing credentials
GET  → Return 405 Method Not Allowed
```

### File Upload API

```text theme={"dark"}
POST → Large body size limit (100MB)
     → Inject S3 credentials
GET  → Normal limit (10MB)
     → Inject read-only credentials
```

## Troubleshooting

### Method Config Not Applied

**Symptoms:** Request uses global config instead of method config

**Check:**

1. Method name matches the request method (matching is case-insensitive — both the config method and request method are upper-cased before comparison, so `POST`, `post`, and `Post` all match)
2. Method config is saved
3. Route is enabled
4. Check logs to see which config was used

### Wrong Headers Injected

**Debug:**

1. Check request logs
2. See "Config Used" field
3. Verify method config has correct headers
4. Check for typos in secret names

### Variables Not Replaced

**Symptoms:** Backend receives literal `{{var:param}}`

**Causes:**

* Query parameter name doesn't match
* Typo in template: `{{var:paramter}}` instead of `{{var:parameter}}`
* Query parameter not provided in request

**Fix:**

1. Check query parameter name in request
2. Match exactly in template
3. Verify in logs

## Related Concepts

* **Global Route Config**: Default configuration used when no method override
* **Secrets**: Encrypted credentials injected via `{{secret:name}}`
* **Variables**: Query parameters accessible via `{{var:name}}`
* **Rate Limiting**: Can be different per method
* **Request Signing**: Can be required only for certain methods

## Next Steps

<CardGroup cols={2}>
  <Card title="Secret Injection" icon="key" href="/getting-started/first-secret">
    Use secrets in method configs
  </Card>

  <Card title="Rate Limiting" icon="gauge" href="/advanced/rate-limiting">
    Different limits per method
  </Card>

  <Card title="Request Signing" icon="signature" href="/security/request-signing">
    Require signatures for mutations
  </Card>

  <Card title="Testing Routes" icon="flask" href="/essentials/routes/testing-routes">
    Test each method configuration
  </Card>
</CardGroup>

***

<CardGroup cols={2}>
  <Card title="📊 Statistics" icon="chart-line">
    * **Level**: intermediate
    * **Time**: 10 minutes
  </Card>

  <Card title="🏷️ Tags" icon="tags">
    `routing`, `configuration`, `http-methods`, `rest-api`
  </Card>
</CardGroup>
