Nothing else is in the URL. No verdict, no personal data, no API key, and never the capture token - the code is minted separately, after the session has concluded, and the two have nothing in common.
Configure the return URL
The URL belongs to the flow, set by an organisation admin, and is frozen into each session when it opens. Nothing in the capture link, the query string or the person’s browser can change where they are sent. It must behttps with a host and no credentials or #fragment; a deployment running a development profile also accepts http://localhost and http://127.0.0.1. Existing query parameters on your URL are kept; code, session_id and state are appended.
Exchange the code
Your server receives the redirect and exchanges the code under its API key:UNSPECIFIED.
The exchange is atomic and single-use: the code is bound to your tenant, spent by the request that wins, and refused afterwards. Refusals are 404 RESULT_CODE_INVALID (no such code for your tenant - another tenant’s code looks exactly like this), 409 RESULT_CODE_CONSUMED (already exchanged) and 410 RESULT_CODE_EXPIRED. If a store fails after the code has been spent, the answer is 503 RESULT_UNAVAILABLE_AFTER_EXCHANGE and its message names the session id to read instead; the code is not given back.
Read the result without the code
The code is a pointer, not the only way in. Read the same result at any time by session id with your API key, so a lost exchange response or a missed webhook costs nothing:status: "PENDING" with no decision.
What is recorded
Issuing, exchanging and refusing a code are audit events (RESULT_CODE_ISSUED, RESULT_CODE_EXCHANGED, RESULT_CODE_REFUSED) that name the session and the outcome. The code itself is stored only as a hash and appears in no log or audit event.
