Coproduct

API reference

POST /onboarding/token-mint

Self-serve, proof-of-possession-bound bearer-token issuance. Hand over an ed25519 public key; get a JWT back bound to it via an RFC 7800 cnf.jkt claim. Every subsequent /a2a call carrying the token MUST also carry X-PoP-Pubkey + X-PoP-Timestamp + X-PoP-Signature or the request is treated as anonymous.

Minimum request

curl -s https://coproduct.fly.dev/onboarding/token-mint \
  -X POST -H 'content-type: application/json' \
  -d '{
    "caller_pubkey": "ed25519:<base64url of 32 raw pubkey bytes>",
    "nonce": "<8-64 char correlator>"
  }'

Optional fields

Response (200 OK)

{
  "access_token": "<base64url header>.<base64url payload>.<base64url signature>",
  "expires_in": 900,
  "token_type": "PoP-Bound",
  "cnf_thumbprint": "<base64url sha256(pubkey)>",
  "principal": "a2a-caller:<cnf_thumbprint>",
  "nonce": "<your input echoed back>"
}

The access_token is a compact-serialization JWT signed by the server's ed25519 key (the same one advertised in the Agent Card as provenance_signer_pubkey). Its payload carries cnf.jkt = sha256(your pubkey), which binds it to your key.

Using the token on /a2a

Each call needs all three PoP headers. The canonical payload you sign is METHOD|PATH|TIMESTAMP, upper-cased method, no query string, integer seconds. ±60 seconds skew is allowed.

TS=$(date +%s)
CANONICAL="POST|/a2a|$TS"
SIG=$(printf '%s' "$CANONICAL" | <ed25519-sign with your private key>)

curl -s https://coproduct.fly.dev/a2a \
  -X POST \
  -H 'content-type: application/json' \
  -H "authorization: Bearer $ACCESS_TOKEN" \
  -H "x-pop-pubkey: ed25519:<your b64url pubkey>" \
  -H "x-pop-timestamp: $TS" \
  -H "x-pop-signature: ed25519:<your b64url signature>" \
  -d '{"jsonrpc":"2.0","id":"1","method":"message/send",
       "params":{"message":"hello"}}'

Security properties

Error responses

Python SDK

The coproduct-a2a Python SDK (source) implements this flow in Client.send_message(...) — it handles the PoP header construction transparently once you've set the private key. The reference integration at coproduct-demo-a2a-langgraph does the full mint + verify round-trip in a LangGraph state machine.