Auth API · nativeSignIn
Redeem the one-time code a native social sign-in handed the Manifold mobile app with the…
POST /api/auth/native/redeem
Redeem the one-time code a native social sign-in handed the Manifold mobile app (manifold://auth?code=…) with the verifier whose SHA-256 started it: the answer is the session the provider's round trip opened in the system browser, as a bearer the app keeps like any sign-in's.
A code redeems for five minutes from the round trip's return. 404 NativeHandoffInvalid for a code that is unknown, expired, never finished, or presented with another verifier — one answer for each. Appends auth.native-handoff-redeemed. Idempotent by state: a handoff is redeemed once, so a retry of the same code with the same verifier inside the five minutes is acknowledged, answers the same session and appends nothing.
Access
Public: The one-time code a native handoff answered with and the PKCE verifier only the page that started it holds, both checked by the route before anything is read
No token: the link, the claim or the first message is the credential, as the description says.
How scopes come from roles: Scopes and roles. Getting a token: Authentication and app tokens.
Retries
Idempotent by state: a handoff is redeemed once, so a retry of the same code with the same verifier inside the five minutes is acknowledged, answers the same session and appends nothing.
Why every write carries a key: Idempotency and retries.
Facts appended
auth.native-handoff-redeemed
What a fact is: Facts and the journal.
AI agent tool
No agent tool. The mobile app's own hand-off of a person's social sign-in from the system browser, redeemed with a verifier only that app holds; a session is never handed to an agent, whose own is the MCP exchange.
Connecting an agent: AI agents.
Example
curl -X POST 'https://auth.getmanifold.io/api/auth/native/redeem' \
-H 'Content-Type: application/json' \
-d '{
"code": "q3Jb7n0yJm1oQvV5c8XkS2eZ4hTgW9aLdRfPuY6iNxE",
"verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
}'const response = await fetch("https://auth.getmanifold.io/api/auth/native/redeem", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
"code": "q3Jb7n0yJm1oQvV5c8XkS2eZ4hTgW9aLdRfPuY6iNxE",
"verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
}),
});
if (!response.ok) throw new Error(`${response.status}: ${await response.text()}`);
const answer = await response.json();{
"code": "q3Jb7n0yJm1oQvV5c8XkS2eZ4hTgW9aLdRfPuY6iNxE",
"verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
}{
"sessionToken": "se1Fq2mWx7cKd9Lr0Tz4",
"user": {
"id": "usr_01a15709-7582-7646-b491-261a138f0650",
"email": "sam@example.com",
"name": "Sam Rivera"
},
"provider": "google"
}The panel writes this call in other languages. It does not send it: Manifold's APIs do not take calls from a web
page on another site, so run the call from your own code or terminal. The whole API as OpenAPI: auth-service.openapi.json. Base URL https://auth.getmanifold.io.
Errors
Every refusal is a status and a JSON body whose _tag names it. A refused call changes nothing.
404
| Refusal | What it means | What to do |
|---|---|---|
NativeHandoffInvalid | No such record in this organization. | Check the id in the path or the body. |
How refusals work everywhere: Errors.