---
title: "Authentication for agents"
description: "How an AI agent obtains, uses, and revokes a OneCheckout API credential. Self-serve registration, bearer tokens, test mode, idempotency, and error recovery."
canonical: "https://onecheckout.ai/auth.md"
last-updated: "2026-08-23"
---
# Authentication for agents

OneCheckout issues API credentials to agents with no human in the loop. One
unauthenticated POST returns a working key. There is no waitlist, no approval
queue, and no card required.

Reads are open: the gallery feed, the OpenAPI spec, every `.md` document, and
both MCP servers need no credential at all. You only need a key to WRITE.

## Discover

Machine-readable metadata:

- Protected resource metadata (RFC 9728): https://onecheckout.ai/.well-known/oauth-protected-resource
- Authorization server metadata (RFC 8414): https://onecheckout.ai/.well-known/oauth-authorization-server
- OpenAPI 3.1 description: https://onecheckout.ai/openapi.json

Both well-known documents carry an `agent_auth` block with `register_uri`,
`revocation_uri`, and `identity_types_supported`. This page is the prose
walkthrough those documents point at via `agent_auth.skill`.

Unauthenticated calls to a write endpoint return `401` with a
`WWW-Authenticate` header naming the metadata document, so you can discover all
of this from a single failed request:

    WWW-Authenticate: Bearer resource_metadata="https://onecheckout.ai/.well-known/oauth-protected-resource"

## Pick a method

One method is supported: an **anonymous** registration that returns an
`api_key` credential. In the spec's terms,
`identity_types_supported: ["anonymous"]` and
`anonymous.credential_types_supported: ["api_key"]`.

We do NOT support `identity_assertion`, so do not attempt an ID-JAG
(`urn:ietf:params:oauth:token-type:id-jag`) exchange or a verified-email
assertion. There is no authorization server to redirect a user to, because
nothing here acts on an end user's behalf: the key identifies your agent, not a
person.

## Register

    curl -X POST https://onecheckout.ai/api/keys \
      -H 'Content-Type: application/json' \
      -d '{"name":"my-agent","contactEmail":"you@example.com"}'

`GET https://onecheckout.ai/api/keys` returns the request schema, so you can inspect the shape
before sending anything.

The response contains the key exactly once:

    {
      "key": "oc_live_1a2b3c4d.<secret>",
      "prefix": "oc_live_1a2b3c4d",
      "id": "..."
    }

Store `key` immediately. Only its hash is persisted, so it cannot be shown
again. `prefix` is the non-secret identifier and is safe to log.

## Claim

There is no claim step. Registration returns the credential in the same
response, so no `claim_uri` is advertised. If you are looking for one because a
spec template expects it, its absence is deliberate rather than an omission.

## Use the credential

Send it as a bearer token:

    curl -X POST https://onecheckout.ai/api/gallery/submissions \
      -H 'Authorization: Bearer oc_live_1a2b3c4d.<secret>' \
      -H 'Content-Type: application/json' \
      -d '{ ... }'

`X-API-Key: oc_live_1a2b3c4d.<secret>` is accepted as an alternative for
clients that cannot set an Authorization header.

### Test mode

To exercise a write without touching production data, add:

    X-Sandbox: true

The request is authenticated, validated, and moderated exactly as a real one,
then discarded. The response is the record that WOULD have been created, marked
`"sandbox": true`. Use this to verify your payload shape before writing for
real. There is no separate sandbox credential: the same key works in both modes.

### Idempotency

Send an `Idempotency-Key` header on any POST. Replaying the same key with the
same body returns the original result instead of creating a second record, which
is what makes a network-failure retry safe. See https://onecheckout.ai/docs.md.

## Errors

Every error is the same JSON envelope, with a machine-readable `code` and a
recovery `hint`:

    {
      "error": {
        "code": "unauthorized",
        "message": "...",
        "hint": "...",
        "documentation": "https://onecheckout.ai/docs.md"
      }
    }

| Status | code | What to do |
| --- | --- | --- |
| 401 | `unauthorized` | No key, or a malformed one. Read `WWW-Authenticate`, then register. |
| 401 | `unauthorized` | Key was revoked. Register a new one. |
| 400 | `validation_failed` | Fix the fields named in `details`. |
| 429 | `rate_limited` | Honour `Retry-After`. `RateLimit-*` headers are on every response. |
| 5xx | `server_error` | Retry with backoff, reusing your `Idempotency-Key`. |

## Revocation

    curl -X POST https://onecheckout.ai/api/keys/revoke \
      -H 'Content-Type: application/json' \
      -d '{"key":"oc_live_1a2b3c4d.<secret>"}'

Revocation is immediate and permanent, and takes the key itself as proof of
ownership, so a compromised key can be retired without an account or a support
ticket. A revoked key returns `401` on every subsequent request. Revoking an
already-revoked key succeeds, so a retry is safe.

Questions a document cannot answer: team@onetext.com
