Organization codes
Minting needs a paid plan. Phone and address coverage needs Premium+.
Every verification a person runs in the Socious Wallet — the identity check included — must be covered by an organization. An organization code is how you cover it: you mint a code, your people type it into the wallet, and each run is attributed to your account and counted against your allowance. Without a code the wallet refuses to start the run at all, so when you ask a membership, a cohort or an electorate to get verified, the code is part of the ask — not an optional way to pick up the bill.
What a code can cover
credential_types names the checks a code covers, and your plan decides what you can
grant:
identity— any paid plan. It is also always included, whatever you send: it is the check the wallet requires a code for in the first place, so a code that could not cover it would be a code that covers nothing.phoneandaddress— Premium+. These spend real money per run, so they need the tier that pays for them.
Minting narrows to your plan rather than refusing: a Standard organization asking for
all three types gets a working identity-only code, and the stored credential_types
come back in the response, so the narrowing is visible rather than silent.
Minting a code
curl -X POST https://api.shinid.com/organizations/ORG_ID/codes \
-H "Authorization: Bearer SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"label": "Governance round, August",
"credential_types": ["identity", "phone", "address"],
"max_redemptions": 500,
"expires_at": "2026-09-30T23:59:59Z"
}'
| Field | Notes |
|---|---|
credential_types | One or more of identity, phone, address. Anything else is rejected; what is stored is narrowed to your plan |
max_redemptions | Omit for uncapped. Set it. An uncapped code is an unbounded authority to spend on your account |
expires_at | Optional, must be in the future |
label | Optional, for your own dashboard |
The response includes code and display_code — the same value, plain and grouped
(SHN7K4M9XQ2TV and SHN-7K4M-9XQ2TV), and the grouped form is the one to put in front
of a human. Typing is forgiving: case, dashes and spaces do not matter, and I, L and
O are read as 1, 1 and 0, so a code transcribed from a projector still lands.
GET /organizations/{id}/codes lists them with redemption_count, active and, when
inactive, inactive_reason. DELETE /organizations/{id}/codes/{code_id} revokes one
immediately.
What the person does
They open the Socious Wallet, type the code, and run the verification. The wallet exchanges the code behind the scenes:
curl -X POST https://api.shinid.com/vouchers/exchange \
-H "Content-Type: application/json" \
-d '{ "code": "SHN-7K4M-9XQ2TV", "did": "did:prism:...", "credential_types": ["identity"] }'
You will not normally call this yourself. It is worth knowing what it enforces:
- The code is checked live. Revoked, expired and exhausted codes are refused, and so is a code whose organization has since left its paid plan. A code never outlives the entitlement behind it.
- The resulting grant is bound to the DID that redeemed it, and is single-use. A grant lifted off the wire cannot be replayed by another wallet.
credential_typesnarrows what this run needs. It can never widen past what the code allows.- The response carries your
organization_name, so the wallet can tell the person who is covering their verification. - The endpoint takes no authentication, since a wallet holder has no account with us. It is throttled to 200 attempts per hour per IP — sized so a whole room onboarding behind one office network does not lock itself out.
A code that covers identity but not the paid modules still verifies the person’s
identity: the wallet runs the parts the grant covers and shows the rest as locked,
rather than failing the person outright.
Choosing between a code and a link
A code is typed by a person into their wallet, with no account and no link to click. That suits an announcement, a printed notice, a room full of people. Use a hosted verification link instead when you are addressing one identified person and can put a URL in front of them — but remember the two are not substitutes: the link asks the person to present a credential, and if they do not hold it yet, acquiring it in the wallet is the step the code covers.
Direct vouchers
POST /vouchers mints the same grant directly, without a code, for a member of a Premium+
organization. You get back a signed token and a wallet_url, and you deliver it however
you like. Codes are for people, vouchers for systems.