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

# Authentication, Status and Retry Contract

> Operation-aware handling across REST and MCP without confusing API errors with execution outcomes

## Authentication by surface

* **Routing REST (`li.quest`)**: public routing endpoints allow keyless use subject to rate limits. Send a key as `x-lifi-api-key` for authenticated usage. Protected endpoints, including `GET /v1/keys/test`, require a valid key.
* **Earn REST (`earn.li.fi`)**: send `x-lifi-api-key`. Do not assume routing access rules or quotas apply to Earn.
* **General MCP, HTTP transport**: the server accepts `Authorization: Bearer <key>` or `X-LiFi-Api-Key`. A Bearer key takes precedence when both are provided. It forwards the selected value upstream as `x-lifi-api-key`; this does not grant permission to sign or broadcast transactions.
* **General MCP, stdio transport**: the server reads `LIFI_API_KEY`. Its `test-api-key` tool calls the routing `/v1/keys/test` endpoint; a successful routing key test does not prove access to every LI.FI product.
* **SDK**: configure the API key using the installed SDK version's documented client options; the client sends the upstream header. See [SDK configuration](/sdk/configure-sdk).
* **CLI and Intents**: use each product's own documented authentication. Do not assume the general MCP's Bearer adapter or routing key is a universal credential.

HTTP header names are case-insensitive. Different capitalization is not a contract mismatch. Never log or publish keys; keep them in server-side configuration.

## Operation-aware outcomes

Keep HTTP status, API numeric code, transfer `status`, and transfer `substatus` separate. The following is client handling guidance, not a new REST response schema or a promise that deployed MCP emits structured fields.

| Observation | Interpretation | Next action |
| - | - | - |
| HTTP 401/403 | Credential or access problem | Check credentials/scope; do not retry unchanged |
| HTTP 400/422 | Invalid request | Correct parameters; do not retry unchanged |
| Status lookup: HTTP 404 / code 1003, or `NOT_FOUND` | Outcome unknown | Bounded polling, then source-chain reconciliation; never automatically resend |
| Quote/route discovery: API code `1002` (`NoQuoteError`) | No usable route for this request | Consider different parameters; no transaction has been authorized |
| Other HTTP 404 | Endpoint or resource not found | Check endpoint and response body; do not assume no route |
| `PENDING` | Still processing | Bounded polling |
| `DONE` + `COMPLETED` | Completed | Reconcile destination evidence |
| `DONE` + `PARTIAL` | Completed with a different asset | Reconcile actual asset; any further swap needs authorization |
| `DONE` + `REFUNDED` | Refund outcome | Reconcile returned funds; do not automatically execute again |
| `FAILED` | Reported execution failure | Inspect source/destination evidence before proposing recovery |
| HTTP 429 | Rate limited | Delay read-only requests, with bounded retry |
| HTTP 5xx or network timeout | Request result unavailable | Bounded retry of safe reads; never infer execution failure |

## Retry boundary

A retry of `GET /status` or quote discovery is not a retry of signing, approval, submission, or deposit. A timeout never authorizes a new transaction. Preserve the original hash and reconcile it before considering replacement. Slippage changes require the user's policy or explicit approval.

If `Retry-After` is present, interpret either delay-seconds or an HTTP date, and do not retry earlier. Otherwise use a bounded exponential backoff with jitter. `ratelimit-reset` is separately documented as seconds until reset; do not treat it as an absolute Unix timestamp. Header availability and quotas can vary by product. The general MCP HTTP client currently calculates its own backoff; do not assume it exposes or enforces `Retry-After` for the calling Agent.

## MCP deployment boundary

An HTTP 200 from the MCP transport is not business success: inspect `CallToolResult.isError` and the tool content. Current general MCP errors may be text rather than a typed error object. Earn capability responses and structured outputs depend on the deployed revision; a GitHub PR is not evidence of deployment.

See [Error Playbooks](/agents/reference/error-playbooks), [Status & Recovery](/agents/workflows/status-recovery), and [Rate Limits](/api-reference/rate-limits).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.