POST /api/link/redeem
Last updated 2 September 2026.
POST/api/link/redeem
Burn the ticket the player came back with and receive their Trivela identity. A ticket is valid for two minutes and exactly one call, and it is consumed by the statement that reads it — a failed redeem cannot be retried.
Request
| Field | Type | Rules | |
|---|---|---|---|
ticket | string | required | The 64-hex value from the ticket query parameter on your return URL. |
subject | string | optional | Optional on the wire; treat as required. If sent, it must equal the subject the ticket was started for, or the ticket is discarded. |
POST /api/link/redeem
Authorization: Bearer sk_yourservice_…
Content-Type: application/json
{ "ticket": "c41a…77d0", "subject": "u_8f31c2" }Send
subject. It is the defence against a ticket started by one person and redeemed in another’s session on your site. A CSRF nonce in your return URL protects against a forged request; only this check protects against a genuine ticket in the wrong hands.Responses
200Linked. Store trivelaUserId, handle and linkedAt under your service id.
{
"service": "yourservice",
"subject": "u_8f31c2", // echoed from the request row, never from your body
"trivelaUserId": "7c0e…", // the durable key
"handle": "coach", // string | null — a player may link before claiming one
"linkedAt": "2026-09-02T09:03:17.000Z",
"alreadyLinked": false
}alreadyLinked: true means this exact pair was already live. Not an error — linkedAt is the original date, and the label is refreshed.
400Malformed body.
{ "error": "Expected a ticket." }
{ "error": "subject must be a string when supplied." }410The ticket is unknown, expired, already used, or was minted for a different service. Start over.
{ "error": "That ticket is not valid, has expired, or has been used." }409The subject you sent is not the one the ticket was started for. The ticket has been burned. No reason key.
{ "error": "subject does not match the one this ticket was issued for. The ticket has been discarded." }409Your user is already linked to a different Trivela account.
{
"error": "That account is already linked to a different Trivela account. Disconnect it there first.",
"reason": "subject_linked_elsewhere"
}409This Trivela account is already linked to a different user of yours.
{
"error": "This Trivela account is already connected to this service under a different account.",
"reason": "account_already_linked"
}401Bad or missing key.
{ "error": "Unknown or missing service key." }Notes
- Verify
serviceandsubjectin the response against what you expect before writing anything. - Call this from a route handler and redirect immediately; see The handshake.