> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.mitu.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.mitu.ai/_mcp/server.

# Request verification

When an AI agent uses one of your tools, Mitu sends the corresponding request to your API. Your backend should verify the request before trusting Mitu-specific headers, customer context or payment information.

When you connect your API, Mitu provides a signing secret with the `mps_...` prefix. Keep this secret on your server and use it only to verify requests sent by Mitu. You do not provide Mitu with your application's own API credential for this purpose.

Request verification is separate from customer authentication. Verification proves that the request came through Mitu, while customer authentication identifies the customer the AI agent is acting for.

## Request headers

Requests sent through Mitu can include the following headers.

| Header                  | Description                                                                                          |
| ----------------------- | ---------------------------------------------------------------------------------------------------- |
| `x-mitu-signature`      | Signature used to verify that the request came through Mitu.                                         |
| `x-mitu-request-id`     | Unique identifier for the forwarded request. Use it when deduplicating operations with side effects. |
| `x-mitu-amount-charged` | Amount associated with a paid request when applicable.                                               |
| `x-mitu-customer-id`    | Mitu customer identifier when the request has customer context.                                      |
| `x-mitu-customer-ref`   | Your customer reference associated with that customer.                                               |
| `x-mitu-agent-id`       | Identifier associated with the agent making the request, when available.                             |
| `authorization`         | The customer's access token when OAuth customer authentication is being used.                        |

Not every request contains every header. Customer headers are only present when a customer has been identified, and payment-specific information is only present where it applies to the payment flow.

Do not use the presence or absence of `x-mitu-amount-charged` as a substitute for request verification. Always verify the signature first.

## Verify the signature

A signed request includes a timestamp and signature value in `x-mitu-signature`.

```http
x-mitu-signature: t=1757601046,v1=9f3c4a...b2d4
```

The signature is produced from the signing secret and the signed payload.

```text
HMAC-SHA256(
  signing_secret,
  "{timestamp}.{request_id}.{amount}.{raw_body}"
)
```

| Component    | Value                                                                       |
| ------------ | --------------------------------------------------------------------------- |
| `timestamp`  | The `t` value from `x-mitu-signature`.                                      |
| `request_id` | The value of `x-mitu-request-id`.                                           |
| `amount`     | The value of `x-mitu-amount-charged`, or an empty string when it is absent. |
| `raw_body`   | The exact request body bytes received by your server.                       |

The body must be verified in the same form that was signed. Parsing JSON and then serialising it again can change whitespace or field ordering and cause a valid signature to fail.

## Node.js example

**`verify.js`**

```js title="verify.js"
const crypto = require('crypto')

app.use(express.json({
  verify: (req, _res, buf) => {
    req.rawBody = buf.toString('utf8')
  },
}))

function verifyMituRequest(req, secret) {
  const header = req.get('x-mitu-signature') || ''

  const parts = Object.fromEntries(
    header.split(',').map((part) => part.split('=')),
  )

  const { t, v1 } = parts

  if (!t || !v1) {
    return false
  }

  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) {
    return false
  }

  const requestId = req.get('x-mitu-request-id')
  const amount = req.get('x-mitu-amount-charged') ?? ''
  const signedPayload = `${t}.${requestId}.${amount}.${req.rawBody}`

  const expected = crypto
    .createHmac('sha256', secret)
    .update(signedPayload)
    .digest('hex')

  if (expected.length !== v1.length) {
    return false
  }

  return crypto.timingSafeEqual(
    Buffer.from(v1),
    Buffer.from(expected),
  )
}
```

The five-minute window in this example is a policy your own backend enforces. Choose a tolerance appropriate for your infrastructure rather than treating the value as fixed.

## Verification rules

Your backend should verify the request before reading Mitu-specific customer or payment context. After verification succeeds, use the request ID to protect operations with side effects from being performed more than once.

Use a timing-safe comparison for signature values and verify against the raw request body rather than reconstructed JSON. A timestamp tolerance should also be enforced so a captured signed request cannot be replayed indefinitely.

## Prevent duplicate side effects

A forwarded request can be retried, so endpoints that create or modify state should handle the same `x-mitu-request-id` more than once without repeating the underlying action.

For example, if a request creates an order, store the relationship between the Mitu request and the order you created:

```text
req_abc123 -> order_8841
```

If `req_abc123` arrives again, return the result associated with `order_8841` rather than creating another order.

Persist the idempotency record together with the business operation where possible. This avoids a race where the order is created successfully but the request ID has not yet been recorded when a retry arrives.

> **Two idempotency directions**
>
> `x-mitu-request-id` helps you deduplicate requests Mitu sends to your API. `Idempotency-Key` is used when your backend sends supported requests to the Mitu API.
>
> They protect different request directions and should not be treated as the same identifier.

## Customer authentication is separate

A verified request can also carry customer identity when the AI agent is acting on behalf of a known customer. If OAuth is being used, the customer's access token can be forwarded so your backend continues applying its existing authentication and authorisation rules.

The Mitu signature proves where the request came from. The customer access token and your own backend rules determine what that customer is allowed to do.

## Related

#### [Keys and secrets](/platform/security/keys-and-secrets)

Understand the signing secret and other credentials used by your integration.

#### [Authentication](/platform/mcp/authentication)

Identify customers using customer keys or OAuth.

#### [Agent payments](/platform/payments/agent-payments)

Understand payment-specific request context.

#### [Webhooks](/platform/webhooks/overview)

Verify webhook deliveries separately with a webhook secret.