Two resources, not one
When you call Issue a credential, the platform creates two kinds of resource at once:- Issuance. The offer session. It has
offerUriandofferQrUri, a status that tracks the offer and acceptance flow (fromofferedtocompleted, or tofailedorexpired), and any errors that happened along the way. - Credentials. One or more, and these are what end up in the user’s wallet. Each has its own id, its own status (
offered,issued, orrevoked), and is what you act on later, for example to revoke it.
credentials[] array:
Which one do you need?
Lifecycles, side by side
Each resource has its own state machine.Capture both ids at issuance time
The issuance and credential ids are both stable from the moment the issuance is created. You don’t need to wait for the user to accept. Store both against your own record when you issue:- Issuance id. Lets you ask “was this offer ever accepted?” later, or wire up the
openid4vc.issuance.completedwebhook. - Credential id. Lets you revoke the credential without hunting for it first.
Read the ids back later
If you didn’t capture an id at issuance time, you can recover it: By issuance id, fetch the issuance back and readcredentials[].id from it:
filter[status], filter[format], filter[credentialTemplateId], and filter[exchange]. Cursor pagination uses page[size], page[before], and page[after]. Listing issuances at GET /v1/issuances takes filter[id] and filter[status] instead.
Filter by template id, not preset id. There is no
filter[presetId]. The issuance response reports the
credentialTemplateId the platform resolved your preset to, so capture it from the first issuance if you want to list
everything issued from that preset later. The value is stable for a given preset within your tenant.
