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

# Call a protected endpoint

> Send a Perflo access token, a fresh DPoP proof, the required scope, and an allowed browser origin.

Every protected application programming interface (API) endpoint requires a Perflo access token and a fresh Demonstrating Proof of Possession (DPoP) proof. Perflo also checks the current client, grant, connected provider, token revocation, route scope, and browser origin.

## Prepare the request credentials

Use credentials issued for the same API environment and registered client. A valid signature alone does not authorize a request.

Before each request, confirm these values:

* The access token came from the issuer discovered for the target environment
* The token audience matches that environment’s API resource
* The grant includes every scope listed on the OpenAPI operation
* The DPoP key matches the key bound to the token
* A browser request uses an exact origin registered to the token’s client

Do not send an ID token or an upstream financial provider token. Perflo rejects those tokens even if they use a JSON Web Token (JWT) format.

## Send both required headers

Protected OpenAPI operations list the `PerfloOAuth` and `PerfloDPoPProof` security schemes together. Send both headers on the same request:

```http theme={null}
Authorization: DPoP your_access_token_here
DPoP: your_dpop_proof_here
```

The `Authorization` header contains the Perflo access token. The `DPoP` header contains a new proof for the exact method and normalized target URI.

The proof must include the access-token hash in `ath`. Its `iat` cannot be older than 60 seconds or more than 10 seconds in the future. Use a unique `jti` for every request.

Never use the Bearer scheme, cookies, query parameters, or request bodies as API credentials. Perflo does not fall back to another credential source when either required header is missing.

## Respond to a nonce challenge

Perflo can require a protected-resource nonce to prevent pre-generated proofs. A nonce challenge returns `WWW-Authenticate` and `DPoP-Nonce` response headers.

Store resource-server nonces separately from authorization-server nonces. Replace the stored resource nonce with the newest `DPoP-Nonce`, then sign a new proof with a new `jti` and `iat`.

Do not retry the challenged proof. Its signature remains valid only for its original claims.

## Send browser requests from the registered origin

Perflo evaluates Cross-Origin Resource Sharing (CORS) against the enabled client identified by the validated token. An accepted preflight does not authenticate the protected request.

The actual request must use the same exact registered origin. Perflo rejects `Origin: null`, wildcard matching, unregistered origins, and origins registered to a different client.

Cross-origin responses never allow credentials. See [Call Perflo from a browser](/oauth/browser-access) for the complete browser flow.

## Handle an authorization failure

Use the response status and challenge to choose the next action:

* `401` means the token, proof, nonce, client, grant, or revocation state failed authentication
* `403` means the authenticated grant lacks a route scope or violates an access policy
* `409` with `provider_reconnect_required` means the connected provider must be reconnected
* `429` with `rate_limit_exceeded` means you must wait for the integer `Retry-After` interval
* `503` with `authorization_keys_unavailable`, `authorization_state_unavailable`, `rate_limit_state_unavailable`, or `operation_state_unavailable` means a required signing-key, live authorization or audit, shared rate-limit, or durable operation-state dependency is unavailable and the request failed closed

See [Handle API errors](/guides/errors) before retrying a failed request.
