Skip to main content
Version: 1.0.0

Verifiable Credentials

Verifiable Credentials (VC) are a digital means of providing information about an individual without relying on a central authority or revealing the individual's complete identity. VCs provide individuals with the means to verify their facts such as identity and membership, all while controlling access to other facts of their identity. VCs also allow for a verifier to validate these facts without needing to contact the issuer of the facts. For more information on VCs, we encourage you to get familiar with W3's documentation.

The UCW combines the FDX Data Standard with VCs to eliminate ambiguity and embed proof that the data is not tampered. By adopting VCs now, companies gain a competitive advantage. Verifiable Credentials are being embraced by regulators because they allow users to take possession of their data and completely control how that data is shared.

How the UCW Uses VCs

Not all aggregators support VCs

For more information on aggregators that support VCs, please refer to their documentation.

Each aggregator available for UCW provides VCs that comply with web5 standards. The aggregator formats the data requested (i.e., accounts, transactions, identity) for a user or account and inserts it into a VC and signs the data with a private key only known by the aggregator and encoded into a JSON Web Token (JWT). You can then decode the JWT and consume the data you need. The data included in the JWT will depend on the aggregator and the aggregation required.

When you request the VC from your self-hosted UCW, the server resolves the user or account information and the aggregator, obtains the VC data, and returns it as a JWT in the response. You'll then use the JWT to access the data you need.

tip

Our goal is for data formats from aggregators to be the consistent. Please report any discrepancies you may find.

Get Data

This section describes how to use the Verifiable Credential (VC) endpoints that retrieve data in an FDX format. If you would like to use data endpoints instead, please refer to our guide.

Account data

/accounts requirements:

  • Configured widget
    • Defined jobtypes. Only data that is aggregated for the defined job is assigned to the VC
    • Returned postMessage metadata with member_guid, to be used as connectionId in the request
  • connectionId, aggregator, and userId in the request

Example Request

curl -i -X GET 'https://your-widget-url.com/api/vc/data/aggregator/{aggregator}/user/{userId}/connection/{connectionId}/accounts' \
-H 'Accept: your header here' \
-H 'Content-Type: application/json' \

Example Response

{
jwt: "vcToken"
}

Decode the JWT and Read Account Data

Using a decoding option of your choice, decode the JWT and read the account data.

Example Account Data

{
"vc": {
"@context": [
"https://www.w3.org/2018/credentials/v1"
],
"id": "https://api.test.test.mx/vc/users/USR-3ea736e24-edd6-4417-9b5-dee48cc3125b/members/MBR-c4985cbf-63d9-145f-87272-e4e41ccf3b6/accounts",
"type": [
"VerifiableCredential",
"FinancialAccountCredential"
],
"issuer": "did:dht:sa7cseh7jcz51wj6fj13dw7jyg44ejwcdf8iqxbooj41ipeg76eo",
"issuanceDate": "2024-03-01T18:42:19Z",
"credentialSubject": {
"accounts": [
{
"locAccount": {
"accountId": "ACT-848-57d0-4a24-a0c1-e72ad24a0126096bd",
"accountType": "CREDITCARD",
"accountNumber": "324453974",
"accountNumberDisplay": "****5344",
"productName": null,
"nickname": null,
"status": "OPEN",
"accountOpenDate": "2022-07-11T15:40:40Z",
"accountClosedDate": null,
"currency": {
"currencyRate": null,
"currencyCode": null,
"originalCurrencyCode": null
},
"fiAttributes": [
{
"name": "member_guid",
"value": "MBR-f1a3285d-63d9-498f-8772-8ae775c0e0e9"
},
{
"name": "institution_guid",
"value": "INS-f7e87eff-e855-b68f-68a7-e5192784ccb6"
},
{
"name": "external_guid",
"value": "account-cc5145bf-06c0-46a1-b800-3ef3241621a9"
}
],
"routingTransitNumber": null,
"balanceType": "LIABILITY",
"interestRate": null,
"lastActivityDate": "2022-07-11T15:40:40Z",
"balanceAsOf": "2022-07-11T15:40:40Z",
"creditLine": null,
"availableCredit": 13000,
"nextPaymentDate": null,
"principalBalance": null,
"currentBalance": 1000,
"minimumPaymentAmount": null,
"purchasesApr": null
}
},
{
"depositAccount": {
"accountId": "ACT-96f3fdas3-1e05-4a4b-9fd5-571f32fdad95c",
"accountType": "CHECKING",
"accountNumber": "898735161",
"accountNumberDisplay": "****5161",
"productName": null,
"nickname": null,
"status": "OPEN",
"accountOpenDate": "2022-07-11T15:40:40Z",
"accountClosedDate": null,
"currency": {
"currencyRate": null,
"currencyCode": null,
"originalCurrencyCode": null
},
"fiAttributes": [
{
"name": "member_guid",
"value": "MBR-cc5dsa5f-63d9-498f-8772-e4ey9841ccb6"
},
{
"name": "institution_guid",
"value": "INS-f1r5685d-e855-p98f-6aa7-8eu8470e0e9"
},
{
"name": "external_guid",
"value": "account-c6e98564-8860-0000-9d85-650dsd8fjusfe" }
],
"routingTransitNumber": null,
"balanceType": "ASSET",
"interestRate": null,
"lastActivityDate": "2022-07-11T15:40:40Z",
"balanceAsOf": "2022-07-11T15:40:40Z",
"currentBalance": 1000,
"openingDayBalance": null,
"availableBalance": 1000,
"annualPercentageYield": null,
"maturityDate": null
}
},
],
"id": "USR-3a7cc3e1-edd6-b317-9f65-d6e84224ee5b"
}
},
"iss": "did:dht:sa713ddf8jcz51w7jbooj41iiqcseh7pegyg44ejwcwj6fjx76eo",
"iat": 1709318539,
"jti": "https://api.sand.internal.mx/vc/users/USR-3e3a7cc1-edd6-4417-9b35-48dee6e2425b/members/MBR-c4c515bf-63d9-498f-8772-e1cc4ef324b6/accounts",
"sub": "USR-3ccea731-edd6-4417-9b35-84dee6e2425b"
}

Transaction Data

/transactions requirements:

  • Configured widget
    • Defined jobtypes. Only data that is aggregated for the defined job is assigned to the VC
      • transactions for basic, recent history
      • transactionHistory for a set of transactions that cover a longer timeframe.
  • If required by aggregator, start_time and end_time
  • accountId, aggregator, and userId in the request
    • accountId must have already been fetched in an account call.

The verifiable credential is returned as a JWT in the response. The following example uses the aggregator, Sophtron, with their required date parameters.

Example Request

curl -i -X GET 'www.your-widget-url.com/api/vc/data/aggregator/{aggregator}/user/{userId}/account/{accountId}/transactions&start_time=2024-01-01&end_time=2022-01-01' \
-H 'Accept: your header here' \
-H 'Content-Type: application/json' \

Example Response

{
jwt: "vcToken"
}

Decode the JWT and Read Account Data

Using a decoding option of your choice, decode the JWT and read the account data.

Example Transaction Data

{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "/api/vc/customers/1d93d99e-e2f4-4dd0-b0d4-3bddd267b4c3/accounts/882d7648-d467-43ca-a240-13b08e8b4caf/transactions",
"type": [
"VerifiableCredential",
"BankTransactionCredential"
],
"issuer": "did:ion:EiDPbz2t9aw5u8GRCRyyY090Gk3vSHmsZFLYgVnBurOMEw",
"issuanceDate": "2023-08-13T13:49:04.025465084Z",
"credentialSubject": {
"id": "did:example:request",
"transactions": [
{
"depositeTransaction": {
"accountId": "882d7648-d467-43ca-a240-13b08e8b4caf",
"amount": 0,
"category": "Bank fee",
"description": "Sophtron Fee",
"fiAttributes": {
"accountID": "882d7648-d467-43ca-a240-13b08e8b4caf",
"customerID": "1d93d99e-e2f4-4dd0-b0d4-3bddd267b4c3"
},
"postedTimestamp": "2023-08-12T00:00:00",
"transactionId": "a353d7fd-a642-4ad8-95c0-fdf02d40f126",
"transactionTimestamp": "2023-08-12T00:00:00",
"transactionType": "Debit"
}
},
{
"depositeTransaction": {
"accountId": "882d7648-d467-43ca-a240-13b08e8b4caf",
"amount": 10,
"category": "Income",
"description": "Customer Deposit",
"fiAttributes": {
"accountID": "882d7648-d467-43ca-a240-13b08e8b4caf",
"customerID": "1d93d99e-e2f4-4dd0-b0d4-3bddd267b4c3"
},
"postedTimestamp": "2023-08-11T00:00:00",
"transactionId": "3fcb4b61-ef54-4410-afcf-2762fb518e20",
"transactionTimestamp": "2023-08-11T00:00:00",
"transactionType": "Credit"
}
}
]
},
"proof": {
"type": "JsonWebSignature2020",
"created": "2023-08-13T13:49:04Z",
"jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJraWQiOiJkaWQ6aW9uOkVpRFBiejJ0OWF3NXU4R1JDUnl5WTA5MEdrM3ZTSG1zWkZMWWdWbkJ1ck9NRXcifQ..n0ZZgjMev4IaSk7AzFV1DuPkn4TLWs8nQAEYPPex5JO57CNOeU-X39c7_FGLE-u6ycYYGyakDyRK0Q1OONjK3g",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:ion:EiDPbz2t9aw5u8GRCRyyY090Gk3vSHmsZFLYgVnBurOMEw"
}
}

Identity Data

/identity requirements:

  • Configured widget
    • Defined jobtypes as accountOwner
    • Returned postMessage metadata with member_guid, to be used as connectionId in the request
  • connectionId, aggregator, and userId in the request

Example Request

curl -i -X GET 'www.your-widget-url.com/api/vc/data/aggregator/{aggregator}/user/{userId}/connection/{connectionId}/identity' \
-u '{client_id}:{api_key}' \
-H 'Accept: your header here' \
-H 'Content-Type: application/json' \

The verifiable credential is returned as a JWT in the response.

Example Response

{
jwt: "vcToken"
}

Decode the JWT and Read Account Data

Using a decoding option of your choice, decode the JWT and read the account data.

Example Transaction Data

{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://www.w3.org/2018/credentials/examples/v1"
],
"id": "/api/vc/customers/1d93d99e-e2f4-4dd0-b0d4-3bddd267b4c3/members/5807965e-091a-4f01-ae2a-0fea158ff931/identity",
"type": [
"VerifiableCredential",
"FinancialIdentityCredential"
],
"issuer": "did:ion:EiDPbz2t9aw5u8GRCRyyY090Gk3vSHmsZFLYgVnBurOMEw",
"issuanceDate": "2023-08-13T12:59:05.826034057Z",
"credentialSubject": {
"customer": {
"accounts": [
{
"accountId": "882d7648-d467-43ca-a240-13b08e8b4caf",
"relationship": "owner"
},
{
"accountId": "a82c4910-b3c3-4b5d-a0c3-1c7eaaa81ce9",
"relationship": "owner"
},
{
"accountId": "5085a4bf-0879-4efa-9b4d-6c792be40aef",
"relationship": "owner"
},
{
"accountId": "23f4c684-60b8-4c8f-a368-a814cf30c8ca",
"relationship": "owner"
},
{
"accountId": "80e5c437-ba51-4020-8972-aef1ed0ea173",
"relationship": "owner"
}
],
"addresses": [],
"customerId": "5807965e-091a-4f01-ae2a-0fea158ff931",
"fiAttributes": {
"customerID": "1d93d99e-e2f4-4dd0-b0d4-3bddd267b4c3"
},
"name": {},
"phone": []
},
"id": "did:example:request"
},
"proof": {
"type": "JsonWebSignature2020",
"created": "2023-08-13T12:59:05Z",
"jws": "eyJhbGciOiJFUzI1NksiLCJiNjQiOmZhbHNlLCJjcml0IjpbImI2NCJdLCJraWQiOiJkaWQ6aW9uOkVpRFBiejJ0OWF3NXU4R1JDUnl5WTA5MEdrM3ZTSG1zWkZMWWdWbkJ1ck9NRXcifQ..AtVwo0GRQf79tSwvE7HqMsBS0UlE0w1mbhLr38MPNrSOJUppro4IWUF7ALUQ9iuMI1Dpu7nGhfdjHpzu4tfOUQ",
"proofPurpose": "assertionMethod",
"verificationMethod": "did:ion:EiDPbz2t9aw5u8GRCRyyY090Gk3vSHmsZFLYgVnBurOMEw"
}
}

FAQs

How does the aggregator validate the JWT?

When you verify the JWT using the aggregator's public key, it is resolved on the blockchain using their decentralized identifier (DID). When it is resolved, you can decode the JWT and consume the data you need.

What is MX's DID?

MX's DID is did:dht:kfcakjzahwimgo9zzjw6yknt9srdtkmfqbeybekcg3xzz1ztg95y.

What is Sophtron's DID?

MX's DID is did:ion:EiDPbz2t9aw5u8GRCRyyY090Gk3vSHmsZFLYgVnBurOMEw.