Overview
Submits the signature produced in Request Challenge to mint a new API key. On success, the raw API key is returned exactly once — store it somewhere safe. GRAIL only retains a hash.
The returned api_key is shown only once. It cannot be retrieved later — if lost, revoke it and mint a new one.
The signature must be a base64-encoded Ed25519 signature of the challenge message (the full string returned by Step 1). Do not send base58 — that produces 400 invalid_signature. See the Authentication & Setup guide for a signer snippet.
This endpoint is rate-limited to 10 requests per minute per IP. Exceeding the limit returns 429 rate_limited.
Request Body
The challenge_id returned from POST /v1/auth/challenge.
Base64-encoded Ed25519 signature of the challenge message, signed by the partner wallet’s private key.
Human-readable label for this key (e.g., "production integration", "staging tests"). Shown in the key list.
Response
The raw API key. Format: grail_partner_<64-hex>. Pass this in the x-api-key header on all subsequent requests. Shown only once.
UUID of the key record. Use this to revoke the key later.
Always "PARTNER" for keys minted via this endpoint.
Echo of the key_name you supplied.
The partner wallet that signed the challenge.
ISO-8601 timestamp of key creation.
Errors
| HTTP | error | When |
|---|
| 400 | invalid_request | Missing challenge_id, signature, or key_name |
| 400 | invalid_challenge | Challenge not found, or already used |
| 400 | challenge_expired | Challenge older than 2 minutes |
| 400 | wallet_revoked | Partner wallet’s status is revoked |
| 400 | invalid_signature | Ed25519 verification failed — most often because the signature was sent as base58 |
| 429 | rate_limited | More than 10 requests in the last minute from this IP |
curl -X POST https://grail-stack-dev.onrender.com/v1/auth/api-key \
-H "Content-Type: application/json" \
-d '{
"challenge_id": "ch_9b5a3a12-7b89-4d6c-9f6a-18c52d3f9e3a",
"signature": "r8JvAw...base64...Q==",
"key_name": "integration test"
}'
{
"api_key": "grail_partner_7f3a...<64 hex chars total>",
"key_id": "0c9bd7e4-6b2e-4f3a-a9a7-1f6e5d4c3b2a",
"scope": "PARTNER",
"key_name": "integration test",
"wallet_address": "Fd31QxW7RRZwvMfNnhNaPvczJpMh7wyzBTWvtMA66wjN",
"created_at": "2026-04-19T12:30:45.123Z"
}