Learn how to configure an OID4VCI Pre-authorized Code flow to issue an mDoc into a digital wallet
Introduction
The OpenID4VCI specification  is an open standard developed by the OpenID Foundation. It leverages the OpenID protocol to support verifiable credentials issuance and management.
In this tutorial we will configure an OID4VCI Pre-authorized Code flow and use it to issue an mDoc into a MATTR GO Hold example app.
User experience
This is the user experience you will build in this tutorial:
- The user launches their GO Hold example app and scans a QR code received from an issuer.
- The GO Hold example app displays what credential is being offered and by what issuer.
- Once the user accepts the offer, they are required to provide a transaction code. This code is provided to the user by the issuer through a different channel (e.g. email, SMS, printed on paper).
- Once the transaction code is provided, the credential is immediately issued to the user’s GO Hold example app. They can now view the credential and present it for verification.
UX considerations
- No prior authentication required: Users are not required to authenticate before the credential is issued. This simplifies the process but assumes the issuer has already verified the user prior to providing the credential offer (e.g., during login to a wallet application or service portal).
- Implicit credential acceptance: The user is not technically required to explicitly accept the credential offer. Depending on how the flow is implemented with wallet providers, the credential can be issued immediately upon scanning the QR code.
- Optional transaction code: The use of a transaction code is optional and can be omitted if not required by the issuer. In this tutorial, we include it to demonstrate how an additional layer of security can be added to the issuance workflow.
Tutorial overview
To build this user experience, the current tutorial comprises the following steps:
- Obtain a MATTR VII access token: You need this to access protected endpoints on your MATTR VII tenant.
- Create Issuer certificates: Required to sign mDocs.
- Create an mDocs credentials configuration: Controls the content and branding of issued Credentials.
- Create and share a Credential offer: Used by digital wallets to trigger the issuance workflow.
- Claim the credential as the holder: Use your GO Hold example app to claim the offered Credential.
Prerequisites
- Complete the sign up form  to get access to a MATTR VII trial tenant.
- Install the MATTR GO Hold example app by following the getting started guide.
We recommend using the MATTR VII Postman collection  in this tutorial. While this isn’t an explicit prerequisite it can really speed things up.
Tutorial steps
Obtain a MATTR VII access token
All of the MATTR VII endpoints you will use in this tutorial are protected, so you will first need to use your login credentials to make a request of the following structure and obtain an access token:
Request
POST https://{auth_server}/oauth/token
auth_server
: Replace with theauth_url
value from your login credentials.
Your auth_url
is not the same as your tenant_url
. auth_url
is only used for obtaining
an access token, while tenant_url
is used for all other requests to your tenant.
Request body
{
"client_id": "F5qaeLDdbvnU9zhA0j4eHUGCHwC1bKtt",
"client_secret": "Wzc8J**********************************************************",
"audience": "learn.vii.au01.mattr.global",
"grant_type": "client_credentials"
}
- Replace
client_id
,client_secret
andaudience
with your own login credentials. - Keep
grant_type
asclient_credentials
.
Response
{
"access_token": "eyJhb********************************************************************",
"expires_in": 14400,
"token_type": "Bearer"
}
Use the returned access_token
value as a bearer token for all requests to your MATTR VII tenant in
the next steps of this tutorial.
You will need to obtain a new access token whenever it expires. We recommend using our Postman collection  to interact with your MATTR VII tenant. This collection includes a pre-request script to obtain an access token when it is missing or expired, as well as pre-configured templates for all available requests.
Create issuer certificates
In this tutorial you are going to issue an mDoc, so you need to have valid IACA.
- Make the following request to your MATTR VII tenant to create an IACA:
POST /v2/credentials/mobile/iacas
The response will include an id
element which you will use in the next step.
- Make the following request to update the created IACA to active:
PUT /v2/credentials/mobile/iacas/{iacaId}
iacaId
: Replace with theid
element returned in the response when you created the IACA in the previous steps.
{
"active": true
}
Your IACA is now active and can be used to sign mDocs.
Create a MATTR VII mDocs credential configuration
Now that you have valid certificates in place, the next component you need is a Credential configuration to define the structure and branding of the issued credential.
Request
Make the following request to create a simple mDoc credentials configuration that includes the holder’s name and e-mail:
POST /v2/credentials/mobile/configurations
Request body
{
"type": "com.example.myfirstpreauthcredential",
"expiresIn": {
"months": 1
},
"claimMappings": {
"com.example.personaldetails.1": {
"name": {
"mapFrom": "claims.name",
"type": "string"
},
"email": {
"mapFrom": "claims.email",
"type": "string"
}
}
},
"branding": {
"name": "My First Pre-Auth Credential",
"description": "For High Assurance Interactions",
"backgroundColor": "#a2d82dff"
},
"includeStatus": true
}
Response
The response will include an id
element. You will use it to create a Credential offer in the next
step.
Create a Credential offer
You now have all the pieces in place and can wrap them all together to generate a Credential offer and share it with the intended holder so that they know what credentials are being offered and by whom.
Request
Make the following request to generate a new Pre-authorized Code flow Credential offer:
POST /v1/openid/offers/pre-authorized
Request body
{
"credentials": ["707e920a-f342-443b-ae24-6946b7b5033e"],
"transactionCodeConfiguration": {
"inputMode": "numeric",
"description": "Please enter the one-time code that was sent to you via email."
},
"claims": {
"name": "John Doe",
"email": "john.doe@example.com"
},
"expiresIn": {
"minutes": 10
}
}
credentials
: Populate the array with theid
element returned in the response when you created an mDocs credentials configuration in the previous step.
In this example, the claims are included directly in the credential offer. This is allowed in the Pre-authorized Code flow because the user’s identity has already been verified. You can provide these claims programmatically when creating the credential offer, or you can reference a Claims source in your credential configuration to dynamically populate the claims in the issued credential.
Response
{
"id": "e6e5e43c-8053-464a-aca4-ca43da765c97",
"uri": "openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Flearn.vii.au01.mattr.global%22%2C%22credentials%22%3A%5B%22b7b380be-1467-446b-8683-1d131e6532be%22%5D%2C%22grants%22%3A%7B%22urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Apre-authorized_code%22%3A%7B%22pre-authorized_code%22%3A%229K3N9UPQD-Hs5f5-gPx0fRJEmb1XTZsWszzXL024pV0%22%2C%22tx_code%22%3A%7B%22length%22%3A6%2C%22input_mode%22%3A%22numeric%22%2C%22description%22%3A%22Please%20enter%20the%20one-time%20code%20that%20was%20sent%20to%20you%20via%20email.%22%7D%7D%7D%7D",
"userId": "6e30dd69-c867-4279-afd3-e6619253b4a4",
"expiresAt": "2025-08-25T01:39:00.523Z",
"transactionCode": "763677"
}
You will need to obtain two important elements from the response:
transactionCode
: This is the one-time code that the user will need to provide in order to claim the credential. In production deployments you will need to provide it to the user through a different channel (e.g., email, SMS, printed on paper).uri
: This URI can be used by a digital wallet to trigger the OID4VCI workflow. Use one of the following tools to convert theuri
value to a QR code (make sure you use thePlain text
option where available) and save the generated QR code as an image file.
MATTR is not affiliated with any of these service providers and cannot vouch for their offerings.
Use the MATTR GO Hold example app to claim the credential
- Open the GO hold example app.
- Select Scan.
- Scan the QR code generated in the previous step.
- Review the credential offer and select Accept.
- Provide the transaction code provided when you created the credential offer.
- Follow the on-screen instructions to claim the credential.
Congratulations, you just configured an end-to-end OID4VCI Pre-authorized Code flow to issue an mDoc into a digital wallet!!!
What’s next?
In this tutorial we have configured a basic OID4VCI Pre-authorized Code flow. However, you can use MATTR VII to create more complex and rich issuance experience. Check out more resources on MATTR Learn that will enable you to:
- Configure a Claims source to retrieve data from compatible data sources and use it in the issued credential.
- Apply branding to issued credentials as part of creating a Credential configuration.
- Experiment with a different issuance flow by completing the OID4VCI Authorization Code flow tutorial.