Skip to content

Proactively mint an errand for a user you already authenticated.

POST
/errand
curl --request POST \
--url https://native-api.sudomimus.com/errand \
--header 'Content-Type: application/json' \
--data '{ "accessToken": "example" }'

Ask, on the application’s own behalf, for an errand side-trip so the user can manage what they share — the on-demand counterpart to the claim-gate 403. Use it when direct-issue would succeed but you want to invite the user to grant OPTIONAL claims that native issuance can never prompt for, or to let a Steam-only user add an email they choose to share.

Authenticated by an access token you already hold for the user (from an earlier direct-issue or Connect redeem). It is verified and its expiry is enforced, then reverse-resolved to the account — so present a fresh one. The access token only identifies the user; it never authorizes the sharing. Every minted ticket therefore forces an in-browser re-authentication before any task runs, so a leaked token cannot alter a user’s grants.

When the account already satisfies the application’s claim policy the response carries errand: null — nothing to do, just direct-issue. Otherwise open errand.url and poll /errand/{errandKey}/status exactly as for the 403 handoff.

Media type application/json
object
accessToken
required

An access token (JWT) the application already holds for the user. Verified server-side with its expiry enforced, then reverse-resolved from its subject (sector subject) claim to the account — so present a currently-valid token, not an expired one.

string
Example generated
{
"accessToken": "example"
}

Either the errand handoff to open, or errand: null when nothing is owed. claims always reports the per-claim state.

Media type application/json
object
errand
required
One of:

The browser side-trip that unblocks a claim-gated direct-issue: a short-lived (30 minutes), single-use bearer URL where the user authenticates (when account data is being written), completes any missing data, and grants consent. The stored task list is server- side only — open the URL and let the page drive. Repeated blocked calls re-hand the same live handoff (same errandKey, original expiresAt) while it has at least 15 minutes left and the owed task scope is unchanged.

object
errandKey
required

Bearer key (ernd_…); also the status-poll path key.

string
url
required

Open this in the user’s system browser.

string format: uri
expiresAt
required
string format: date-time
claims
required

Per-claim view across the three shareable claims, carried on both the 200 (why is a claim absent from the minted token) and the claim-gate 403 (what is still owed).

object
email
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
firstName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
lastName
required

One shareable claim: what the application requests (requirement) joined with the user’s standing decision (state). UNKNOWN means the user was never asked; DENIED means the user explicitly declined.

object
requirement
required

The developer’s policy for the claim. SYNTHETIC guarantees the claim is present but permits a generated placeholder (a stand-in name, a proxy email) when the user has not shared real data — unlike REQUIRED it never blocks issuance or raises an errand.

string
Allowed values: OFF OPTIONAL REQUIRED SYNTHETIC
state
required
string
Allowed values: UNKNOWN GRANTED DENIED
Example
{
"claims": {
"email": {
"requirement": "OFF",
"state": "UNKNOWN"
},
"firstName": {
"requirement": "OFF",
"state": "UNKNOWN"
},
"lastName": {
"requirement": "OFF",
"state": "UNKNOWN"
}
}
}

The access token is missing, malformed, expired, or no longer resolves to an account.

Media type application/json

Error response body. The Native service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}

The application or the account is disabled.

Media type application/json

Error response body. The Native service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}

Error response.

Media type application/json

Error response body. The Native service emits { "reason": "<SymbolDescription>" } for known failure modes. When the reason symbol’s description begins with PRIVATE, the body is empty (zero bytes) and only the HTTP status carries signal — both reason and the body itself are absent in that case.

object
reason

Stable machine-readable reason code.

string
Example generated
{
"reason": "example"
}