Skip to main content

Your First API Call (Credential Factory)

note

Credential Factory was formerly IaaS (Issuer as a Service). Only the name changed: keep using your existing hostname (for example iaas.stg.iden2.app) and API paths.

This walkthrough takes you from zero to a 201 Created credential offer. You'll create an offer, render the QR code, and watch the offer get claimed.

Prerequisites​

  • An OAuth access token with the issuance.credential.create scope (Authentication)
  • Staging environment access
  • A wallet app that supports OID4VCI (to actually claim the credential)

The examples below assume you have already acquired a token and stored it in $ACCESS_TOKEN — see Authentication for the token-acquire step.

1. Create a credential offer​

curl -X POST https://iaas.stg.iden2.app/api/v1/iaas/credential-offers \
-H "Authorization: Bearer $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"authenticationMethod": "PRE_AUTHORIZED",
"credentialConfigurationId": "VerifiedPerson_vc+sd-jwt",
"credentialData": {
"givenName": "Alice",
"familyName": "Smith",
"dateOfBirth": "1990-01-15"
},
"offerTtlSeconds": 300
}'

A successful call returns 201 Created:

{
"offerId": "550e8400-e29b-41d4-a716-446655440000",
"offerUrl": "openid-credential-offer://...?credential_offer=...",
"qrCodeDataUrl": "data:image/png;base64,iVBORw0KGgo...",
"status": "pending",
"createdAt": "2025-01-15T10:00:00Z",
"expiresAt": "2025-01-15T10:05:00Z",
"credentialConfigurationId": "VerifiedPerson_vc+sd-jwt",
"credentialType": "VerifiedPerson"
}

The two fields you care about right now:

  • qrCodeDataUrl — a ready-to-render PNG QR code. Drop it straight into an <img> tag.
  • offerId — use this to poll the offer status.

2. Show the QR code​

<img src="data:image/png;base64,iVBORw0KGgo..." alt="Scan with your wallet to receive your credential" />

That's it — the offerUrl encoded in the QR drives the entire holder flow. See QR Code Rendering for alternatives.

3. Poll for the result​

curl https://iaas.stg.iden2.app/api/v1/iaas/credential-offers/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer $ACCESS_TOKEN"

Poll every 3–5 seconds until the credential is issued (claimedAt is present, with status claimed or accepted) or the offer ends (rejected, expired or revoked):

StatusMeaningWhat to do
pendingWaiting for the holder to scan and claimKeep polling
claimedCredential issued to the holder's wallet 🎉Done — claimedAt is now present (and holderBinding, when the wallet supplied one)
acceptedHolder accepted the offerDone if claimedAt is present; otherwise the credential hasn't been issued yet — keep polling
rejectedHolder declined the offer (failureReason wallet_rejected)Stop — create a new offer if they retry
expiredThe offer expired before a credential was issuedCreate a new offer; don't retry the same offerId
revokedYou revoked the credential, or the offer failed (see failureReason)Stop

The wallet can accept or reject before or after the credential is issued. An offer accepted before issuance stays accepted, and claimedAt and credentialId are added when the credential is issued.

Troubleshooting​

ResponseLikely cause
401Missing, invalid, or expired access token — re-acquire a token (Authentication)
403Your token lacks the required scope, or your configuration isn't permitted to issue this credential type
404The credentialConfigurationId doesn't exist — check the spelling, including the vc+sd-jwt suffix
400Malformed JSON, missing required field, or selectiveDisclosure keys that don't match credentialData keys

All error bodies follow the shared error model — the detail field tells you exactly what went wrong.

Next steps​