This quick start walks you through IXO Credentials on devnet, end to end, with IXO's test issuer and test verifier. Use it to see what an offer, a stored credential, a proof request and a revocation look like before you build your own issuer, verifier or wallet. The parts you run yourself take about 10 minutes.
Test tooling only. The devnet test issuer issues fake "Test Credential" credentials whose claims are whatever the test operator typed, and the test verifier only reports whether a proof was shown. Never use either for real people, and never treat a Test Credential as evidence of anything.
The devnet services
| Service | Address | DID |
|---|---|---|
| Credentials worker | https://dev.credentials.ixo.earth (API reference) | did:web:dev.credentials.ixo.earth |
| Auth Hub wallet | https://dev.auth.ixo.earth/credentials | |
| Test issuer | https://test-issuer.dev.credentials.ixo.earth | did:web:test-issuer.dev.credentials.ixo.earth |
| Test verifier | https://test-verifier.dev.credentials.ixo.earth (API reference) | did:web:test-verifier.dev.credentials.ixo.earth |
The test issuer issues one type:
| Field | Value |
|---|---|
| Configuration id | TestCredential (dc+sd-jwt, signed with Ed25519, bound to a did:ixo key) |
vct | https://test-issuer.dev.credentials.ixo.earth/types/TestCredential |
| Claims (all selectively disclosable) | name, age_over_18, age_over_21, level, member_number, favourite_colour, city |
| Lifetime | 30 days, with a status list entry for every credential |
| Status list | https://dev.credentials.ixo.earth/status/did:web:test-issuer.dev.credentials.ixo.earth/test1 |
The test verifier asks for age_over_18 ("Confirm that you are over 18") or for no claim at all ("Confirm that your identity is verified"), and accepts only credentials from the test issuer.
Prerequisites
curland Node.js 22 or later.- A devnet IXO account: sign in at
https://dev.auth.ixo.earth. Your DID isdid:ixo:followed by your devnet IXO address (ixo1…), shown on the Hub's wallet pages.
Step 1 — Read the live services
Everything a wallet or verifier reads is public. Start with the Credentials worker and its DID document:
curl -s https://dev.credentials.ixo.earth/health
curl -s https://dev.credentials.ixo.earth/.well-known/did.json{"status":"ok","version":"0.1.0","timestamp":"2026-11-09T03:38:03.329Z","environment":"devnet"}Read the test issuer's OpenID4VCI metadata, the way a wallet finds the credential and token endpoints:
curl -s https://test-issuer.dev.credentials.ixo.earth/.well-known/openid-credential-issuer
curl -s https://test-issuer.dev.credentials.ixo.earth/.well-known/oauth-authorization-server{
"issuer": "https://test-issuer.dev.credentials.ixo.earth",
"token_endpoint": "https://test-issuer.dev.credentials.ixo.earth/oid4vci/token",
"grant_types_supported": ["urn:ietf:params:oauth:grant-type:pre-authorized_code"],
"token_endpoint_auth_methods_supported": ["none"],
"pre-authorized_grant_anonymous_access_supported": true
}Read both catalog entries. This is where the Hub takes each sender's name and card look from:
curl -s https://dev.credentials.ixo.earth/v1/catalog/issuers/did:web:test-issuer.dev.credentials.ixo.earth
curl -s https://dev.credentials.ixo.earth/v1/catalog/verifiers/did:web:test-verifier.dev.credentials.ixo.earth{
"sender_key": "did:web:test-verifier.dev.credentials.ixo.earth",
"entry": {
"did": "did:web:test-verifier.dev.credentials.ixo.earth",
"name": "IXO Test Verifier (devnet)",
"accepts": [
{
"purpose": "Confirm that you are over 18",
"vct": "https://test-issuer.dev.credentials.ixo.earth/types/TestCredential",
"claims": ["age_over_18"],
"issuers": ["did:web:test-issuer.dev.credentials.ixo.earth"]
}
],
"color": "#5b21b6"
},
"updated_at": 1794145603
}The answer above is shortened: the live entry also lists IdentityLevel1 and the possession-only purpose.
Step 2 — Verify a status list with the kit
Install the kit and check the test issuer's status list the way a verifier does: resolve the issuer's did:web, verify the token's signature and sub, and read one bit.
mkdir credentials-try && cd credentials-try
npm init -y && npm pkg set type=module
npm install @ixo/credentials-kit@0.1.1import { createWebResolver } from '@ixo/credentials-kit/did';
import { verifyStatusListToken, statusAt } from '@ixo/credentials-kit/status';
const issuer = 'did:web:test-issuer.dev.credentials.ixo.earth';
const uri = `https://dev.credentials.ixo.earth/status/${issuer}/test1`;
const resolver = createWebResolver({ fetch });
const issuerDoc = await resolver(issuer); // https://test-issuer.dev.credentials.ixo.earth/.well-known/did.json
const token = await (await fetch(uri)).text();
const list = await verifyStatusListToken(token, { uri, issuerDoc });
console.log('signed by', list.kid, 'ttl', list.ttl);
console.log('index 0 is', statusAt(list.bits, 0, list.bitsPerEntry) === 0 ? 'valid' : 'revoked');node check-status.mjssigned by did:web:test-issuer.dev.credentials.ixo.earth#key-1 ttl 60
index 0 is validStep 3 — Save a test credential in the Hub
The test issuer's offer endpoint and the test verifier's check endpoint are operated by IXO and are not public: whoever can call them makes the Hub show an offer or a request to the person named. To receive a test offer and a test request, post your devnet DID in the IXO Community Slack or send it to assistant@ixo.world, and say which claims you want on your Test Credential (for example age_over_18: true).
When the offer arrives:
- Open
https://dev.auth.ixo.earth/credentials. The offer from "IXO Test Issuer (devnet)" is under Needs you. - Choose Review, look at the card and what it holds, and choose Save to my credentials.
- The Hub collects the credential over OpenID4VCI with your own key, checks it (signature,
subis you,cnfis your key, status), and stores it in your Vault. It appears under Your credentials.
Step 4 — Answer a test request
When the test verifier asks you for proof:
- Open the request in the Hub (from Needs you, or from the
wallet_urlyou were sent). - The page shows who asks (the verifier's catalog name), why (its
purpose), the credential that will be used and the details that will leave with their values: for "Confirm that you are over 18", onlyage_over_18. - Choose Just this time and Share. The Hub sends an encrypted, key-bound presentation to the verifier's
response_uri; the check becomesverified.
Choose Don't share instead to see a decline: the verifier receives access_denied and the check expires.
Verify the result
- The Hub's activity page (
https://dev.auth.ixo.earth/credentials/activity) lists the save and the share in plain words. - The credential's page shows who issued it, when it expires, whether it is revoked and who it was shared with.
- When the test operator revokes your Test Credential, the issuer republishes
test1at once, verifiers seerevokedwithin the list'sttl(60 seconds), and the Hub marks the credential as revoked.
Troubleshooting
No offer arrives
The worker refuses an offer for a DID that does not exist on devnet (unknown_subject), more than 2 waiting offers from one issuer for one person (too_many_pending), and offers from a sender you blocked (blocked). Check the DID is your devnet did:ixo:ixo1…, deal with waiting offers, and unblock the test issuer on the Sharing page if you blocked it.
The request says "You don't have this yet"
The test verifier accepts only credentials from did:web:test-issuer.dev.credentials.ixo.earth. Save a Test Credential first; for "over 18" it must carry age_over_18.
Next steps
- Build your own verifier against devnet: accept
did:web:test-issuer.dev.credentials.ixo.earthand theTestCredentialvct, and ask your own devnet account for proof. See Request proof. - Build your own issuer: deposit an offer for your own devnet DID and save it in the devnet Hub. See Issue a credential.
- Read every endpoint and error code in the Credentials API reference.