Proactively mint an errand for a user you already authenticated.
const url = 'https://native-api.sudomimus.com/errand';const options = { method: 'POST', headers: {'Content-Type': 'application/json'}, body: '{"accessToken":"example"}'};
try { const response = await fetch(url, options); const data = await response.json(); console.log(data);} catch (error) { console.error(error);}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.
Request Body required
Section titled “Request Body required ”object
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.
Example generated
{ "accessToken": "example"}Responses
Section titled “ Responses ”Either the errand handoff to open, or errand: null when nothing is
owed. claims always reports the per-claim state.
object
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
Bearer key (ernd_…); also the status-poll path key.
Open this in the user’s system browser.
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
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
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.
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
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.
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
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.
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.
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
Stable machine-readable reason code.
Example generated
{ "reason": "example"}The application or the account is disabled.
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
Stable machine-readable reason code.
Example generated
{ "reason": "example"}default
Section titled “default ”Error response.
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
Stable machine-readable reason code.
Example generated
{ "reason": "example"}