Create a Credential Offer
This guide walks you through creating a credential offer from an existing profile. The offer generates an OID4VCI credential offer URL that can be claimed by any compliant wallet.
Prerequisites
Before creating an offer, ensure you have:
- Issuer2 Service – A running issuer2 service
- Credential Profile – An active credential profile
Create an Offer
CURL
Endpoint: POST /v2/{target}/issuer-service-api/credentials/offers | API Reference
Example Request (Pre-Authorized Flow)
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{profileTarget}/issuer-service-api/credentials/offers' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"authMethod": "PRE_AUTHORIZED",
"valueMode": "BY_REFERENCE",
"expiresInSeconds": 300
}'
Body
{
"authMethod": "PRE_AUTHORIZED",
"valueMode": "BY_REFERENCE",
"expiresInSeconds": 300
}
Path Parameters
orgID– Your organization's Base URL. For example, if your organization is namedtest, your default Base URL will betest.enterprise-sandbox.walt.devwhen using the sandbox environment.profileTarget– The resource identifier for the credential profile ({organizationID}.{tenantID}.{issuerServiceID}.{profileId}), e.g.waltid.tenant1.issuer1.profile-abc123
Body Parameters
Required Parameters
authMethod: String – The authentication method for the offerPRE_AUTHORIZED– Pre-authorized code flow (no user authentication)AUTHORIZED– Authorization code flow (user authentication required)
Optional Parameters
valueMode: String – How the credential offer is delivered (default:BY_REFERENCE)BY_REFERENCE– Offer URL contains a reference; wallet fetches full offerBY_VALUE– Full credential offer embedded in URL
issuerStateMode: String – Whether to include issuer state (default:OMIT)OMIT– No issuer stateINCLUDE– Include issuer state for session correlation
expiresInSeconds: Integer – Offer validity duration in seconds (default: 300). Set to-1for no expiration.txCode: Object – Transaction code (PIN) configuration for pre-authorized flowtxCodeValue: String – Specific PIN value (if not provided, one is generated)runtimeOverrides: Object – Override profile values for this offer. See Runtime Overrides.
Response
Success Response (201)
{
"offerId": "abc123-def456-ghi789",
"profileId": "waltid.tenant1.issuer1.profile-abc123",
"profileVersion": 1,
"authMethod": "PRE_AUTHORIZED",
"issuerStateMode": "OMIT",
"expiresAt": 1704067500000,
"credentialOffer": "openid-credential-offer://?credential_offer_uri=https%3A%2F%2Fwaltid.enterprise-sandbox.waltid.dev%2Fv2%2Fwaltid.tenant1.issuer1%2Fopenid4vci%2Fcredential-offer%3Fid%3Dabc123-def456-ghi789"
}
Response Fields
offerId: String – Unique identifier for this offerprofileId: String – The profile used to create this offerprofileVersion: Integer – The version of the profile usedauthMethod: String – The authentication methodissuerStateMode: String – The issuer state modeexpiresAt: Long – Unix timestamp when the offer expirestxCodeValue: String – The PIN value (only for pre-authorized flow with txCode)credentialOffer: String – The OID4VCI credential offer URL
Transaction Code (PIN)
For pre-authorized flow, you can require a PIN for additional security:
{
"authMethod": "PRE_AUTHORIZED",
"txCode": {
"inputMode": "numeric",
"length": 6,
"description": "Please enter the PIN sent to your email"
}
}
txCode Parameters:
inputMode: String – Input type (numericortext)length: Integer – Length of the PINdescription: String – Description shown to the user
If you want to specify the PIN value:
{
"authMethod": "PRE_AUTHORIZED",
"txCode": {
"inputMode": "numeric",
"length": 6
},
"txCodeValue": "123456"
}
Runtime Overrides
You can override any profile value for a specific offer using runtimeOverrides:
{
"authMethod": "PRE_AUTHORIZED",
"runtimeOverrides": {
"issuerDid": "did:key:z6MkNewDid...",
"issuerKeyId": "waltid.tenant1.kms1.differentKey",
"subjectId": "did:key:z6MkSubjectDid...",
"credentialData": {
"@context": [
"https://www.w3.org/2018/credentials/v1"
],
"type": ["VerifiableCredential", "CustomCredential"],
"credentialSubject": {
"customField": "customValue"
}
},
"mapping": {
"id": "<uuid>"
},
"credentialStatus": {
"statusCredentialConfig": "waltid.tenant1.credentialstatus.config2",
"initialStatus": "0x0"
},
"notifications": {
"webhook": {
"url": "https://different-webhook.com/callback"
}
}
}
}
Available Override Fields
| Field | Description |
|---|---|
issuerDid | Override the issuer DID |
issuerKeyId | Override the signing key |
x5Chain | Override the X.509 certificate chain |
subjectId | Set the credential subject ID |
credentialData | Override the credential data |
mapping | Override the data mapping |
idTokenClaimsMapping | Override ID token claims mapping |
mDocNameSpacesDataMappingConfig | Override mDoc data mapping |
credentialStatus | Override credential status configuration |
notifications | Override notification settings |
Examples
Pre-Authorized Flow with PIN
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{profileTarget}/issuer-service-api/credentials/offers' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"authMethod": "PRE_AUTHORIZED",
"txCode": {
"inputMode": "numeric",
"length": 4
},
"expiresInSeconds": 600
}'
Authorization Code Flow
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{profileTarget}/issuer-service-api/credentials/offers' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"authMethod": "AUTHORIZED",
"issuerStateMode": "INCLUDE",
"expiresInSeconds": 900
}'
Offer with Custom Credential Data
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{profileTarget}/issuer-service-api/credentials/offers' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"authMethod": "PRE_AUTHORIZED",
"runtimeOverrides": {
"credentialData": {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"type": ["VerifiableCredential", "UniversityDegree"],
"credentialSubject": {
"degree": {
"type": "MasterDegree",
"name": "Master of Computer Science"
}
}
}
}
}'
Offer by Value
curl -X 'POST' \
'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{profileTarget}/issuer-service-api/credentials/offers' \
-H 'accept: application/json' \
-H 'Authorization: Bearer {yourToken}' \
-H 'Content-Type: application/json' \
-d '{
"authMethod": "PRE_AUTHORIZED",
"valueMode": "BY_VALUE"
}'
Using the Credential Offer
The credentialOffer URL in the response can be:
- Displayed as QR Code – User scans with their wallet app
- Sent as Deep Link – User clicks link on mobile device
- Embedded in Email/Message – User clicks to open in wallet
Example Decoded Offer URL
openid-credential-offer://?credential_offer_uri=https://waltid.enterprise-sandbox.waltid.dev/v2/waltid.tenant1.issuer1/openid4vci/credential-offer?id=abc123-def456-ghi789
When the wallet resolves this URL, it will:
- Fetch the full credential offer from the issuer
- Display the credential details to the user
- Request the credential using the appropriate flow
Next Steps
- Session Events – Monitor issuance progress in real-time
- Notifications – Configure webhook notifications
Last updated on April 8, 2026
