Create a Verifiable Presentation

View as Markdown
When to use

A verifier has asked you for a presentation — typically by sharing a Proof Request URL/QR (see §5.2). You want to compile one or more of your VCs into a signed VP and submit it.

Before you begin
  • The verifier’s Proof Request (a Presentation Definition per DIF Presentation Exchange v2).
  • The VCs that satisfy the request.
Steps
  1. Open the Proof Request (URL or QR scan in the wallet).
  2. The portal/wallet matches the request against your held VCs and shows you which credentials would satisfy each input descriptor. 3. Approve. The portal calls POST /api/v1/presentations/create (vc.go:316).
  3. The API:
    • Fetches the named VCs.
    • Constructs a VP envelope.
    • Signs the VP with your DID’s authentication key.
    • Returns the VP JSON.
  4. The portal/wallet then submits the VP to the verifier (typically via POST /api/v1/presentations/verify on the verifier’s side, or a callback URL specified in the Proof Request).
API & SDK
cURLTypeScript SDK
$curl -X POST https://adid.dev/api/v1/presentations/create \
> -H "Authorization: Bearer $ACCESS_TOKEN" \
> -H "Content-Type: application/json" \
> -d '{
> "holderDid":"did:adi:0x9a2c...",
> "credentialIds":["urn:uuid:c5b7e3..."],
> "challenge":"verifier-nonce-abc",
> "domain":"verifier.example.com"
> }'
1const vp = await client.createPresentation({
2 holderDid: 'did:adi:0x9a2c...',
3 credentialIds: ['urn:uuid:c5b7e3...'],
4 challenge: 'verifier-nonce-abc',
5 domain: 'verifier.example.com',
6});

Response (truncated):

1{
2 "verifiablePresentation": {
3 "@context":["https://www.w3.org/ns/credentials/v2"],
4 "type":["VerifiablePresentation"],
5 "holder":"did:adi:0x9a2c...",
6 "verifiableCredential":[ { ... } ],
7 "proof":{ "type":"Ed25519Signature2020", "challenge":"verifier-nonce-abc", "domain":"verifier.example.com", "proofValue":"z3..." }
8 }
9}
Verify

The verifier’s portal will show “Presentation received → verifying…” and within ~1 s display the verdict. You should see a matching record in your own /presentations/history (if surfaced — currently part of §5.4 Verification History for the verifier side).

Troubleshooting
CodeCauseFix
400 NO_MATCHING_CREDENTIALNone of your VCs satisfy the requestAcquire the missing credential first.
403 NOT_HOLDERThe VC’s credentialSubject.id is not your DIDYou cannot present someone else’s credential.
409 PRESENTATION_REJECTED_BY_VERIFIERVerifier policy rejected the VPSee response body for reasons[].

3.2.5. Checking a Credential’s Revocation Status ##### When to use

You hold a credential and want to confirm it has not been revoked. The status check is also performed automatically every time you open a credential’s detail page.

Before you begin

You have a credential ID.

Steps (manual)
$curl https://adid.dev/api/v1/credentials/urn:uuid:c5b7e3.../status

(No auth needed — this endpoint is public, registered at router.go:68.)

Response:

1{
2 "credentialId":"urn:uuid:c5b7e3...",
3 "revoked": false,
4 "statusListId":"abcd",
5 "statusListIndex": 42,
6 "checkedAt":"2026-04-26T12:00:00Z"
7}
How it works under the hood

The handler reads the bit at the credential’s statusListIndex from the RevocationRegistry contract. Bit 1 = revoked, bit 0 = active. See §4.4.3 for the bitstring encoding.

Troubleshooting
CodeCauseFix
404 CREDENTIAL_NOT_FOUNDCredential never existed or was deleted from indexConfirm credential ID.
502 CHAIN_UNREACHABLERPC downRetry.