Skip to main content

Well-known documents

3 operations under /.well-known (GET): parameters, status codes, refusal bodies, and the same request in curl, HTTP, Python and TypeScript.

4 min read
View MarkdownEdit on GitHub

Base URL: https://api.codespar.dev

None of the operations below takes a credential: the published document declares them open. See Authentication for the rest of the API.

GET /.well-known/codespar-receipt-keys.json

GEThttps://api.codespar.dev/.well-known/codespar-receipt-keys.json
No credential

Receipt verification keys (JWKS)

The public half of the key that signs agentic receipts, so a party with no CodeSpar credential can check one. An agentic receipt carries two seals: receipt_sig, an HMAC under the consumer's own secret, which proves the payment to whoever holds that secret and to nobody else; and receipt_sig_ed25519, made with the key published here.

To verify: take receipt_sig_kid from the receipt, find the key with that kid below, build codespar-receipt:v1:<receipt_id>:<chain> and check the base64url signature over those UTF-8 bytes with any Ed25519 verifier. x is the raw 32-byte public key, base64url (RFC 8037).

Keys ROTATE and a retired key stays listed — that is what keeps an old receipt verifiable. A revoked key is removed entirely: its private half is assumed compromised, so signatures it made are worth nothing. An empty keys means this deployment publishes none, which is consistent with its receipts carrying a null receipt_sig_kid.

Every kid names the DEPLOYMENT that minted it — <did>#<namespace>-<n>, and key_namespace repeats the namespace this document serves. A receipt_sig_kid that is ABSENT here therefore means the receipt came from another environment (a sandbox receipt checked against production, most often), which is unknown_key and NOT a tampered receipt. Before ent#1641 the id was <did>#<n> in every environment, so receipts sealed then carry an id that more than one document may claim; they keep verifying against the document of the environment that issued them and nowhere else.

Collect receipts (the receipt a human payer of a Collect link gets) are signed by the same keys. collect_receipt states their signing string and digest recipe.

Responses

StatusBodyDescription
200objectOK

Response 200

FieldTypeRequiredDescription
algorithmstringyes—
collect_receiptobjectyesHow a Collect receipt is verified with the keys above (ent#1848). A Collect receipt is signed by the same keys; its signing string is codespar-collect-receipt:v1:<receipt_id>:<digest>, where digest is SHA-256 of the RFC 8785 canonical JSON of the receipt's document. Appended after keys: every field above is unchanged.
issuerstringyes—
key_namespacestringyesThe deployment whose keys this document serves, and the namespace every kid below carries. A kid from another namespace is unknown here, not forged.
keysarray of objectyes—
signing_stringstringyesThe template of the bytes a signature covers, stated so a verifier needs nothing else from us.
Example request
curl -X GET https://api.codespar.dev/.well-known/codespar-receipt-keys.json \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /.well-known/codespar-receipt-keys.json HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/.well-known/codespar-receipt-keys.json",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/.well-known/codespar-receipt-keys.json", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/.well-known/codespar-receipt-keys.json");
Example response 200
application/json
{
  "issuer": "string",
  "key_namespace": "Example",
  "algorithm": "string",
  "signing_string": "string",
  "keys": [
    {
      "kid": "string",
      "kty": "string",
      "crv": "string",
      "x": "string",
      "alg": "string",
      "use": "string",
      "status": "string",
      "created_at": "string",
      "retired_at": "string"
    }
  ],
  "collect_receipt": {
    "signing_string": "string",
    "digest_recipe": {
      "canonicalization": "string",
      "digest": "string",
      "document_fields": [
        "string"
      ]
    },
    "signature": "string"
  }
}

GET /.well-known/oauth-authorization-server

GEThttps://api.codespar.dev/.well-known/oauth-authorization-server
No credential

Authorization-server metadata (RFC 8414)

The three endpoint URLs below, absolute under the issuer, plus what this server supports: response_types_supported: ["code"], grant_types_supported: ["authorization_code", "refresh_token"], code_challenge_methods_supported: ["S256"] and token_endpoint_auth_methods_supported: ["none"].

Read the last two together: this is a PUBLIC client with no secret, and PKCE S256 is mandatory rather than preferred. plain is never advertised and is refused at the authorize endpoint. Host-aware, like the document above.

Responses

StatusBodyDescription
200objectOK

Response 200

FieldTypeRequiredDescription
authorization_endpointstringyes—
code_challenge_methods_supportedarray of stringyes—
grant_types_supportedarray of stringyes—
issuerstringyes—
registration_endpointstringyes—
response_types_supportedarray of stringyes—
scopes_supportedarray of stringyes—
token_endpointstringyes—
token_endpoint_auth_methods_supportedarray of stringyes—
Example request
curl -X GET https://api.codespar.dev/.well-known/oauth-authorization-server \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /.well-known/oauth-authorization-server HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/.well-known/oauth-authorization-server",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/.well-known/oauth-authorization-server", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/.well-known/oauth-authorization-server");
Example response 200
application/json
{
  "issuer": "string",
  "authorization_endpoint": "https://example.com/hook",
  "token_endpoint": "https://example.com/hook",
  "registration_endpoint": "https://example.com/hook",
  "response_types_supported": [
    "string"
  ],
  "grant_types_supported": [
    "string"
  ],
  "code_challenge_methods_supported": [
    "string"
  ],
  "token_endpoint_auth_methods_supported": [
    "https://example.com/hook"
  ],
  "scopes_supported": [
    "string"
  ]
}

GET /.well-known/oauth-protected-resource

GEThttps://api.codespar.dev/.well-known/oauth-protected-resource
No credential

Protected-resource metadata (RFC 9728)

The document an MCP client fetches after a 401, from the resource_metadata the WWW-Authenticate header points at resource and authorization_servers are the same origin: this API is its own authorization server.

Host-aware. The issuer is derived from the request's Host, so the copy served on a custom domain advertises that domain and not this document's servers[0] — a client that pasted one origin gets tokens minted for it (RFC 8707 resource indicators).

Responses

StatusBodyDescription
200objectOK

Response 200

FieldTypeRequiredDescription
authorization_serversarray of stringyes—
bearer_methods_supportedarray of stringyes—
resourcestringyes—
scopes_supportedarray of stringyes—
Example request
curl -X GET https://api.codespar.dev/.well-known/oauth-protected-resource \
  -H "Authorization: Bearer $CODESPAR_API_KEY"
GET /.well-known/oauth-protected-resource HTTP/1.1
Host: api.codespar.dev
Authorization: Bearer $CODESPAR_API_KEY
import os
import requests

res = requests.get(
    "https://api.codespar.dev/.well-known/oauth-protected-resource",
    headers={"Authorization": f"Bearer {os.environ['CODESPAR_API_KEY']}"},
)
res.raise_for_status()
data = res.json()
const res = await fetch("https://api.codespar.dev/.well-known/oauth-protected-resource", {
  method: "GET",
  headers: {
    Authorization: `Bearer ${process.env.CODESPAR_API_KEY}`,
  },
});

const data = await res.json();
const result = await cs.api.get("/.well-known/oauth-protected-resource");
Example response 200
application/json
{
  "resource": "string",
  "authorization_servers": [
    "string"
  ],
  "bearer_methods_supported": [
    "string"
  ],
  "scopes_supported": [
    "string"
  ]
}
Well-known documents | CodeSpar