Appearance
Issuer OID4VCI Support
The Universal Issuer supports OID4VCI credential issuance. You provide the credential schema, format, and claim values; the service generates a Credential Offer that a wallet can use to receive the signed credential.
Before issuing credentials, you must configure the oid4vci setting for your account as described in Issuer Configuration. The configuration must include at least one credential schema and a DID registered in your Wallet Service.
API Reference
See API Reference.
Create a Credential Offer (Pre-Authorized Code Flow)
The pre-authorized code flow is the simplest issuance path. Your backend stages the credential claims upfront, and the service returns a Credential Offer URL that the wallet can immediately exchange for a credential — no user login step is involved.
Request
bash
curl -X POST "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/authorize/pre-authorize" \
-H "Authorization: Bearer b082c420-df67-4b06-899c-b7c51d75fba0" \
-H "Content-Type: application/json" \
-d '{
"claims": {
"issuanceDate": "2023-11-15T10:00:00-07:00",
"expirationDate": "2027-11-15T12:00:00-06:00",
"credentialSubject": {
"family_name": "Abt",
"given_name": "Bernd",
"birth_date": "1962.10.26",
"age_over_18": true,
"age_in_years": 62,
"birth_country": "AT",
"resident_city": "St. Poelten",
"resident_country": "AT",
"issuing_country": "AT",
"issuing_authority": "Miniwahr",
"nationality": ["AT"]
}
},
"schema": "EuPid2023_sd_jwt_dc"
}'1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Request Body
- Content-Type:
application/json
| Field | Required | Description |
|---|---|---|
claims | Yes | Map of credential claim values to include in the issued credential. |
schema | Yes | The credential schema key, as configured in Issuer Configuration. |
txCode | No | Transaction code configuration. When present, the wallet must supply a matching PIN to redeem the offer. |
txPin | No | The expected PIN value that the wallet must present when exchanging the pre-authorized code. |
receiverEmail | No | Email address to send the Credential Offer (with QR code) to. |
receiverName | No | Display name of the email recipient. |
Example with PIN:
json
{
"claims": {
"given_name": "John",
"family_name": "Doe",
"birthdate": "1990-01-01"
},
"schema": "example_schema_1",
"txCode": {
"input_mode": "numeric",
"length": 6,
"description": "Enter the 6-digit code sent to your phone"
},
"txPin": "123456"
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Success Response
- Status Code:
200 OK - Content-Type:
application/json
json
{
"credentialOfferUrl": "openid-credential-offer://?credential_offer_uri=eyJ...",
"requestId": "abc123def456",
"issuanceStatusUrl": "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/issuance-status?requestId=abc123def456"
}1
2
3
4
5
2
3
4
5
| Field | Description |
|---|---|
credentialOfferUrl | The Credential Offer URL to present to the wallet, typically rendered as a QR code. The wallet scans this to start the issuance process. |
requestId | Unique identifier for this issuance request. Use it to poll the issuance status. |
issuanceStatusUrl | Ready-to-use URL for polling the issuance status of this request. |
Error Responses
| Status | Description |
|---|---|
400 Bad Request | Invalid request body, or the schema is missing or not configured for the account. |
500 Internal Server Error | Server-side error during processing. |
Create a Credential Offer (Authorization Code Flow)
The authorization code flow adds a user authentication step before the credential is issued. The user is redirected to an external OIDC Identity Provider (IdP) to log in; once authenticated, the wallet receives an authorization code it exchanges for the credential.
This flow requires an externalIdp block in the Issuer Configuration. Claims can be provided upfront at initialization, or fetched automatically from a configured claims_endpoint after the user authenticates — see Claims Modes below.
Flow Overview
Tenant Backend Service Wallet External IdP Claims Endpoint
| | | | |
|--POST /auth-code-> | | | |
|<--credentialOfferUrl| | | |
| | | | |
(out of band)
|--[QR code / deep link / email]-------> | | |
| |<--GET /.well-known/openid-credential-issuer |
| |<--GET /credential_offer_uri/{requestId} |
| |<--POST /par (optional, RFC 9126) | |
| |<--GET /authorize--| | |
| |--302 redirect---->| | |
| | |--login--------->| |
| |<--GET /callback?code=<--------------| |
| | | | |
| [if claims_endpoint configured] | |
| |--GET/POST {claims_endpoint_url}------------------> |
| |<--{ claims }---------------------------------------- |
| | | | |
| |--302 redirect---->| (?code=...) | |
| |<--POST /token-----| | |
| |<--POST /credential| | |
| |---credential----->| | |1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Claims Modes
The authorization code flow supports two ways to supply credential claims:
Mode 1 — Claims provided upfront
You provide the full claim set when calling POST /authorize/auth-code. This works the same as the pre-authorized code flow, with the addition of the user authentication step.
Use this when you already know the user's claims at the time you generate the Credential Offer — for example, when the issuer backend is the system of record.
Mode 2 — Claims fetched dynamically via claims_endpoint
You omit claims from the initialization request. After the user authenticates with the external IdP, the service calls your configured claims_endpoint, forwarding the IdP access token so your endpoint can identify the user and return the appropriate claims.
Use this when claims are held in a system that can only be queried after user identity is confirmed — for example, a government registry or an HR system that gates access by verified identity.
To use this mode, configure claims_endpoint in the schema configuration. See Claims Endpoint for the full contract.
If
claimsis omitted and noclaims_endpointis configured for the schema, the request is rejected with400 Bad Request.
Step 1: Initialize the Flow
Your backend calls POST /authorize/auth-code to stage the issuance request and receive a Credential Offer URL.
Mode 1 — with claims:
bash
curl -X POST "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/authorize/auth-code" \
-H "Authorization: Bearer b082c420-df67-4b06-899c-b7c51d75fba0" \
-H "Content-Type: application/json" \
-d '{
"claims": {
"given_name": "Bernd",
"family_name": "Abt",
"birth_date": "1962-10-26",
"issuing_country": "AT"
},
"schema": "EuPid2023_sd_jwt_dc"
}'1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Mode 2 — without claims (fetched after authentication):
bash
curl -X POST "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/authorize/auth-code" \
-H "Authorization: Bearer b082c420-df67-4b06-899c-b7c51d75fba0" \
-H "Content-Type: application/json" \
-d '{
"schema": "EuPid2023_sd_jwt_dc"
}'1
2
3
4
5
6
2
3
4
5
6
Request Body Fields:
| Field | Required | Description |
|---|---|---|
schema | Yes | The credential schema key, as configured in Issuer Configuration. |
claims | No* | Map of credential claim values. Required when claims_endpoint is not configured for the schema. |
receiverEmail | No | Email address to send the Credential Offer (with QR code) to. |
receiverName | No | Display name of the email recipient. |
txCodeandtxPindo not apply to the authorization code flow. User authentication through the external IdP serves the equivalent purpose.
Success Response:
json
{
"credentialOfferUrl": "openid-credential-offer://?credential_offer_uri=...",
"requestId": "f1e2d3c4-b5a6-7890-abcd-ef1234567890",
"issuanceStatusUrl": "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/issuance-status?requestId=f1e2d3c4-b5a6-7890-abcd-ef1234567890"
}1
2
3
4
5
2
3
4
5
The credentialOfferUrl encodes a Credential Offer whose grants object contains an authorization_code entry. The issuer_state field in that grant is set to the requestId, which ties the wallet session to this staged request through all subsequent steps.
Step 2: Wallet Sends an Authorization Request
The wallet sends an authorization request to the /authorize endpoint, including the issuer_state from the credential offer and a PKCE code_challenge. Optionally, the wallet may first submit its parameters via the /par endpoint (RFC 9126) and present the returned request_uri at /authorize instead.
The service looks up the externalIdp configuration for your account, performs OIDC discovery, and redirects the wallet to the IdP's authorization endpoint.
Step 3: External IdP Authenticates the User
The user logs in at the external IdP. The IdP redirects back to the service's fixed callback URL:
https://oid4vci.example.com/1.0/{accountId}/v1/authorize/callback1
Important: The exact callback URL depends on how your account is configured and may differ if accessed through an API gateway. See Redirect URI for how this URL is derived and how to register it with your IdP.
If a claims_endpoint is configured for the schema, the service calls it at this point using the IdP access token. The returned claims are stored and used when the wallet requests the credential. If the claims endpoint is unreachable or returns an error, the issuance is marked as FAILED and the wallet receives an OAuth error response — your backend can detect this by polling the issuanceStatusUrl.
Step 4: Token and Credential Issuance
After the callback, the service redirects the wallet back to its redirect_uri with ?code=<authorization_code>. The wallet then:
- Exchanges the code at
POST /tokenwith grant typeauthorization_code. - Presents the access token at
POST /credentialalong with a proof of possession to receive the signed credential.
These steps follow the same path as the pre-authorized code flow.
Error Responses
| Status | Description |
|---|---|
400 Bad Request | externalIdp is not configured, claims were omitted without a claims_endpoint configured, or the request body is otherwise invalid. |
500 Internal Server Error | Server-side error during processing. |
Track the Credential Issuance Status
Every issuance request includes an issuanceStatusUrl in the response. Poll this URL to follow the progress of a credential issuance — useful for displaying status in your UI or triggering downstream actions once the credential is issued.
Request
bash
curl -X GET "https://api.godiddy.com/1.0.0/universal-issuer-oid4vci/v1/issuance-status?requestId=db7e3771-4df7-4424-8e0b-5813e7e3d161" \
-H "Authorization: Bearer b082c420-df67-4b06-899c-b7c51d75fba0"1
2
2
Success Response
- Status Code:
200 OK - Content-Type:
application/json
json
{
"metadata": {},
"credential": "ey....",
"requestId": "db7e3771-4df7-4424-8e0b-5813e7e3d161",
"status": "ISSUED"
}1
2
3
4
5
6
2
3
4
5
6
| Field | Description |
|---|---|
status | Current state of the issuance. See Issuance Status Values. |
requestId | The issuance request ID, matching the value returned by the Credential Offer endpoint. |
credential | The issued verifiable credential. Present only when status is ISSUED. Returned as a string for JWT-VC and SD-JWT formats, or as an object for JSON-LD credentials. |
metadata | Additional credential metadata, when available. |
Issuance Status Values
| Status | Description |
|---|---|
INITIALIZED | The issuance request has been created and the Credential Offer has been issued. Waiting for the wallet to start the flow. |
AUTHENTICATED | The user has successfully authenticated with the external IdP (authorization code flow only). Claims have been fetched if a claims_endpoint is configured. |
IN_PROGRESS | The wallet has exchanged the authorization code for an access token and the credential is being signed. |
ISSUED | The credential has been successfully issued to the wallet. |
FAILED | The issuance failed. Common causes: claims endpoint returned an error, IdP authentication failed, or the wallet did not complete the flow within the session window. |
API Endpoints
The paths below show the service's endpoint structure. The actual URLs you call may include an API gateway prefix or differ slightly depending on your account setup — use the https://api.godiddy.com placeholder and the URL patterns shown in the curl examples above as the authoritative reference.
Endpoints Called by Your Backend
| Method | Path | Description |
|---|---|---|
POST | /1.0.0/universal-issuer-oid4vci/v1/authorize/pre-authorize | Stage claims and obtain a pre-authorized Credential Offer URL. |
POST | /1.0.0/universal-issuer-oid4vci/v1/authorize/auth-code | Stage an issuance request and obtain an authorization-code Credential Offer URL. Requires externalIdp configuration. Claims may be provided upfront or omitted when claims_endpoint is configured. |
GET | /1.0.0/universal-issuer-oid4vci/v1/issuance-status | Poll the issuance status for a given requestId. |
Endpoints Called by the Wallet
| Method | Path | Description |
|---|---|---|
GET | /1.0/{accountId}/v1/credential_offer_uri/{requestId} | Fetch the Credential Offer object when the offer URL uses credential_offer_uri by reference. |
GET | /.well-known/openid-credential-issuer/1.0/{accountId}/v1 | Credential issuer metadata. |
GET | /.well-known/oauth-authorization-server/1.0/{accountId}/v1 | OAuth authorization server metadata. |
GET | /1.0/{accountId}/v1/jwks | JSON Web Key Set used to verify tokens issued by this service. |
POST | /1.0/{accountId}/v1/token | Exchange a pre-authorized code or authorization code for an access token. |
POST | /1.0/{accountId}/v1/credential | Issue a verifiable credential. Requires a valid access token and a proof-of-possession JWT. |
POST | /1.0/{accountId}/v1/nonce | Obtain a cryptographic nonce for use in proof-of-possession JWTs. |
POST | /1.0/{accountId}/v1/par | Pushed Authorization Request (RFC 9126). Submits authorization parameters and returns an opaque request_uri. Authorization code flow only. |
GET | /1.0/{accountId}/v1/authorize | Authorization endpoint. Redirects the wallet to the external IdP for user authentication. Authorization code flow only. |
GET | /1.0/{accountId}/v1/authorize/callback | External IdP callback. Completes the authentication handshake, fetches claims if a claims_endpoint is configured, and redirects the wallet back with an authorization code. Must be registered as an allowed redirect URI in the external IdP. Authorization code flow only. |