Send a credential offer

Once a credential offer is created, you can send the offer to the intended holder in one of the following methods:

Prerequisites

  • Access to MATTR VII APIs. If you’re experiencing any difficulties, contact us.

  • DIDs:

    • Issuer DID: This is a did:web that identifies the issuer who attests the claims in the credential are accurate. Refer to create a did:web if you need assistance in creating one. You can only sign Web Credentials using DIDs with a ed25519 or bls12381g2 key type. Note that MATTR VII creates did:webs with both of these key types by default.

    • Subject DID: This is a did:key that identifies the intended holder of the credential. This DID is usually retrieved from the intended holder's digital wallet. Refer to create a did:key if you need assistance in creating one for testing this feature. In production environments you must have a secure way to obtain it:

      • Use DID Auth for any new interactions.

      • Ask the user to share their wallet DID (MATTR Showcase wallet or MATTR GO users can do this by navigating to Settings > Advanced > Public DID).

      • Request an existing credential as part of a verification workflow, and extract the DID from that interaction.

  • The id identifier of a credential configuration, returned in the response when you created the credential configuration.

For Web and Compact Credential, the Issuer must use the same DID to issue all credentials offered as part of the configured issuance flow. Using different DIDs to offer different credentials is not currently supported by MATTR VII.

Send in a message

Similar to other MATTR VII messaging operations, this process comprises two steps:

Encrypt the message

Request

Make the following request to encrypt the message:

http
Copy to clipboard.
1POST https://YOUR_TENANT_URL/v1/messaging/encrypt
json
Copy to clipboard.
1{
2    "senderDidUrl": "did:web:organization.com#CU6dJt9p8t",
3    "recipientDidUrls": [
4      "did:key:z6MkgmEkNM32vyFeMXcQA7AfQDznu47qHCZpy2AYH2Dtdu1d"
5    ],
6    "payload": {
7      "id": "731961f2-bdc3-4f1e-8d59-cc308fd60ec8",
8      "type": "https://mattr.global/schemas/verifiable-credential/offer/OidcCredentialProvider",
9      "from": "did:web:organization.com",
10      "created_time": 1616466734,
11      "body": {
12        "uri": "openid-credential-offer://?credential_offer=%7B%22credential_issuer%22%3A%22https%3A%2F%2Ftenant.vii.mattr.global%22%2C%22credentials%22%3A%5B%2220d6bbe6-a978-447c-b5bd-f33b6dca19e2%22%5D%2C%22request_parameters%22%3A%7B%22login_hint%22%3A%22user%40example.com%22%2C%22prompt%22%3A%22login%22%7D%7D"
13    }
14  }
15}
  • senderDidUrl: The sender's DID URL, obtained from the id field of the first keyAgreement entry of the DID document. Refer to our DID tutorial for more information.

  • recipientDidUrls: Use the intended holder's Subject DID.

  • payload:

    • id: Use the credential configuration id,

    • type: Use the value from the example to indicate that this message includes a credential offer.

    • from: Use your Issuer DID.

    • created_time: Time of creation (Epoch Unix timestamps). The value must be a number and not a string, otherwise the holder will not be able to accept the credential offer.

  • body:

Response

json
Copy to clipboard.
1{
2  "jwe": {
3    "protected": "eyJhbGciOiJYQzIwUCJ9",
4    "recipients": [
5      {
6        "header": {
7          "alg": "ECDH-1PU+A256KW",
8          "kid": "did:key:z6MkgmEkNM32vyFeMXcQA7AfQDznu47qHCZpy2AYH2Dtdu1d#z6LSsvqSJkBvVEsDC8cxMHuQ3sKoLRMXB1MdtoLrMUq6A8Rg",
9          "epk": {
10            "kty": "OKP",
11            "crv": "X25519",
12            "x": "JOLnYaD7L-Rszz7fczPhn6MkNre25PUsztzB1RHoz14"
13          },
14          "skid": "did:key:z6MkreuqFq6WrwozTeGKuUDz8bniTFRNAg8f3ZB862YdLp7v#z6LScyz3YLToyoKwZE6Tfq65hgZUkZdHrC4ZqohcUH9X6Twx"
15        },
16        "encryption_key": "ag5iKzjJOth9Wa68dCVKJW_vnO_Ga0zSJgQp5rIUg69HCzIjuNYhDg"
17      }
18    ],
19    "ciphertext": "xpW-D6sDPpWc_jk87nEyxPX7JQV8_OZpaQft7ySQ5XmNhoj-lQyDkXDncOCyhB7yMSdZrRBNQjKxlEbpY_WLk1hBoWfsTeszVSAuFbX_VKUSJ7GR6rcnWGVNgDfKS8GsyC_owtswXatkF_65_mzFOygctkUmd2eI5bcpQpWjhw2vqnvnWkb7l2J27aWFF_c9cu52dB559j8lwLYyYC9oSMgV5piB6ppfrWBGo_DigjxvJcAYcjFYqFcT6A1nphPhwVTQ2HNfJodbQoseHub8UQdG4qAOcggq5DI84tbqor1SU9rdPH03jPkLgoO_aeXyJg5meITXoFSiu_tRfvf8QQ6vKq6pkTTXs8zKXcBCGhGIyKBNBG4R4RIY1UffTMnJQQQGBble3P06pGOnsnSop0BtygelB9M0ZEwnAUSAQqN1RR4AQwWcn9nH6hHEu1pMhSvhCuFNAPWS-hg24JGGw8Xe3EEZlLH0PM8qpUAfksPq",
20    "iv": "FJq5zKvuPiUQIdRcMtiChHCJByuY8XK9",
21    "tag": "u8kT0VAAtTswjGXxNpuX0g=="
22  }
23}

The result is a message payload constructed in JWM format.

Send the message

Request

Make the following request to send the encrypted jwe object as a message:

http
Copy to clipboard.
1POST https://YOUR_TENANT_URL/v1/messaging/send
json
Copy to clipboard.
1{
2  "to": "did:key:z6MkgmEkNM32vyFeMXcQA7AfQDznu47qHCZpy2AYH2Dtdu1d",
3  "message": {
4    "protected": "eyJhbGciOiJYQzIwUCJ9",
5    "recipients": [
6      {
7        "header": {
8          "alg": "ECDH-1PU+A256KW",
9          "kid": "did:key:z6MkgmEkNM32vyFeMXcQA7AfQDznu47qHCZpy2AYH2Dtdu1d#z6LSsvqSJkBvVEsDC8cxMHuQ3sKoLRMXB1MdtoLrMUq6A8Rg",
10          "epk": {
11            "kty": "OKP",
12            "crv": "X25519",
13            "x": "JOLnYaD7L-Rszz7fczPhn6MkNre25PUsztzB1RHoz14"
14          },
15          "skid": "did:key:z6MkreuqFq6WrwozTeGKuUDz8bniTFRNAg8f3ZB862YdLp7v#z6LScyz3YLToyoKwZE6Tfq65hgZUkZdHrC4ZqohcUH9X6Twx"
16        },
17        "encryption_key": "ag5iKzjJOth9Wa68dCVKJW_vnO_Ga0zSJgQp5rIUg69HCzIjuNYhDg"
18      }
19    ],
20    "ciphertext": "xpW-D6sDPpWc_jk87nEyxPX7JQV8_OZpaQft7ySQ5XmNhoj-lQyDkXDncOCyhB7yMSdZrRBNQjKxlEbpY_WLk1hBoWfsTeszVSAuFbX_VKUSJ7GR6rcnWGVNgDfKS8GsyC_owtswXatkF_65_mzFOygctkUmd2eI5bcpQpWjhw2vqnvnWkb7l2J27aWFF_c9cu52dB559j8lwLYyYC9oSMgV5piB6ppfrWBGo_DigjxvJcAYcjFYqFcT6A1nphPhwVTQ2HNfJodbQoseHub8UQdG4qAOcggq5DI84tbqor1SU9rdPH03jPkLgoO_aeXyJg5meITXoFSiu_tRfvf8QQ6vKq6pkTTXs8zKXcBCGhGIyKBNBG4R4RIY1UffTMnJQQQGBble3P06pGOnsnSop0BtygelB9M0ZEwnAUSAQqN1RR4AQwWcn9nH6hHEu1pMhSvhCuFNAPWS-hg24JGGw8Xe3EEZlLH0PM8qpUAfksPq",
21    "iv": "FJq5zKvuPiUQIdRcMtiChHCJByuY8XK9",
22    "tag": "u8kT0VAAtTswjGXxNpuX0g=="
23  }
24}
  • to: Use the intended holder's Subject DID.

  • message: Use the content of the jwe object from the previous step response. Note that you do not need to include the preceding jwe attribute, only the content of the object.

Response

200 response indicates that the message payload was sent to the service endpoint of the dereferenced DID Document (or the default MATTR service endpoint).

Send as a QR code

Embedding the offer URI in a QR code is currently only supported for Web and Compact Credentials.

A common way to allow a mobile wallet user to claim a credential is to encode the offer URI into a QR code. You could even print out the QR code.

You can use a tool similar to the following to convert the URI to a QR code (make sure you use the Plain text option where available):

MATTR is not affiliated with any of these service providers and cannot vouch for their offerings.

Make sure the QR code is large enough in size to be resolvable by a phone camera; 200px square is generally fine.

Once the QR code is created, you can send it to the intended holder via your preferred communication channel.

You can enable the intended holder to open the offer URI directly from a mobile device by creating a deep link. Perform base64 encoding of the offer URI and then use the encoded URI to create a link of the following structure:

http
Copy to clipboard.
1global.mattr.wallet://accept/{base64Url(openid-credential-offer://...)}

For example:

http
Copy to clipboard.
1 global.mattr.wallet://accept/b3BlbmlkLWNyZWRlbnRpYWwtb2ZmZXI6Ly8_Y3JlZGVudGlhbF9vZmZlcj0lN0IlMjJjcmVkZW50aWFsX2lzc3VlciUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGdGVuYW50LnZpaS5tYXR0ci5nbG9iYWwlMjIlMkMlMjJjcmVkZW50aWFscyUyMiUzQSU1QiUyMjIwZDZiYmU2LWE5NzgtNDQ3Yy1iNWJkLWYzM2I2ZGNhMTllMiUyMiU1RCU3RA

Once the deep link is created, you can send it to the recipient via your preferred communication channel.

When sending a deep link to a MATTR GO Wallet, replace the scheme with your app bundle ID. The following example shows a deep link for a MATTR GO Wallet that has com.example.wallet as its app bundle ID:

http
Copy to clipboard.
1 com.example.wallet://accept/b3BlbmlkLWNyZWRlbnRpYWwtb2ZmZXI6Ly8_Y3JlZGVudGlhbF9vZmZlcj0lN0IlMjJjcmVkZW50aWFsX2lzc3VlciUyMiUzQSUyMmh0dHBzJTNBJTJGJTJGdGVuYW50LnZpaS5tYXR0ci5nbG9iYWwlMjIlMkMlMjJjcmVkZW50aWFscyUyMiUzQSU1QiUyMjIwZDZiYmU2LWE5NzgtNDQ3Yy1iNWJkLWYzM2I2ZGNhMTllMiUyMiU1RCU3RA

For MATTR Pi Wallet SDK customers, refer to your own implementation for deep linking requirements and best practices.

What's next?

Once you've used one of the available methods to send the offer URI to the intended holder, the next step is for them to accept the offer and trigger the credential issuance.