Exchange a ticket
Turn the ticket an execution issued into a reusable token.
Why this exists. Running an engine every month should not mean keeping somebody’s bank password in your database. Tokenization moves that problem: you run the credentials once, we keep them encrypted, and you keep a token that only works for that engine, that customer and that set of features — through your application and no other.
Neither half opens the credentials alone. The key you receive here is not the encryption key: it is one input to a derivation that also needs a secret living only in our runtime, and the result — an AES-256-GCM key — exists only for the moment it is used. We store the ciphertext and a non-reversible verifier of your key, never the key itself. The full design is in the Credential Tokenization guide.
How you get here. Start an execution with base_configurations.tokenized_access: true. If your application is allowed to tokenize, the 202 carries a ticket. That ticket is single-use and short-lived: it exists to be exchanged, here, for the real token.
What you get back. A token_id and a token_key, plus the context the token is locked to: engine, customer, the locking_hash of the credentials, and the features it may request. Store both halves and treat the key like a password — it is the only copy, nothing on our side holds it, and it is never shown again. Lose it and the stored credentials can no longer be opened by anyone: connect the same account again and exchange the new ticket — it renews this token with a new key.
One token per connection. A connection is your application, one engine, one customer_id and one account at that source — the account is what locking_hash identifies. When the ticket belongs to a connection you already hold a token for, this call renews that token instead of minting a second one: the same token_id, a new token_key, renewed: true. The old key stops working at that moment, so keep the new one in its place. That is how you keep a list of your customers’ connections without duplicates: one entry per token_id — Managing your customers’ connections is the practical guide.
The token expires 90 days after this exchange, and using it does not extend that. When it passes, the stored credentials are deleted. Track date_expiration and renew the connection before it lapses — a new execution with the credentials, and its ticket exchanged here. Send the token to Start a Tokenized Execution.
A 403 covers every way this can fail — no such ticket, wrong ticket, already exchanged, expired, another application’s. That is deliberate: an attacker guessing tickets learns nothing from the answer.
A 409 (t10n_exchange_in_progress) means another request is exchanging this same ticket at this moment — a retry that overlapped the first try. Retry after the Retry-After seconds: the exchange is safe to repeat, and a first attempt that never finished leaves nothing lost — the ticket works again.
This endpoint needs to be executed with an app secret, so should always be used in server side without exposing the secret to customers.
Authentication
Request
The execution whose ticket you are exchanging — the one you asked tokenized access for.
The ticket that execution returned. Single-use: this call spends it.
Response
200 OK
The token, and the only copy of your half of the key. Store both: the key is not recoverable and we do not keep it — without it the credentials cannot be opened, by us or by anyone.
renewed: true means the ticket belonged to a connection you already hold a token for: token_id is that token, and this key replaces the one you kept.
The ticket is spent by this call. Asking again with the same one answers 403.
true when the ticket renewed a connection you already had — the same application,
source, customer and account: token_id is the one you stored, and token_key replaces
the key you kept for it, which no longer works. false for a new connection.