Create a Credential Profile

This guide walks you through creating a credential profile, which defines the default configuration for issuing a specific type of credential.

Prerequisites

Before creating a profile, ensure you have:

  • An Issuer2 service — A running issuer service. See Setup.
  • A KMS key — A key for signing credentials, in a KMS Service under the same tenant.
  • An issuer identity — Either a DID or an X.509 certificate (choose per the format table below).

The table below shows which issuer identification method (DID or X.509 certificate) is supported for each credential format:

FormatDIDsX.509 Certificates
JWT (W3C)
SD-JWT (W3C)
SD-JWT VC (IETF)
ISO mDoc

✓ supported · – not available


Create a Profile

CURL

Endpoint: POST /v2/{target}.{profileId}/issuer-service-api/credentials/profiles | API Reference

The new profile's own ID is the last path segment of the target (like service creation), i.e. {target}.{profileId} — here waltid.tenant1.issuer1.profile-abc123.

Example Request
curl -X 'POST' \
  'https://{orgID}.enterprise-sandbox.waltid.dev/v2/{target}.profile-abc123/issuer-service-api/credentials/profiles' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer {yourToken}' \
  -H 'Content-Type: application/json' \
  -d '{
  "name": "Open Badge Credential Profile",
  "credentialConfigurationId": "OpenBadgeCredential_jwt_vc_json",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "issuerDid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
  "w3cVersion": "W3CV2",
  "credentialData": {
    "@context": [
      "https://www.w3.org/ns/credentials/v2",
      "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
      "https://purl.imsglobal.org/spec/ob/v3p0/extensions.json"
    ],
    "type": ["VerifiableCredential", "OpenBadgeCredential"],
    "issuer": {
      "type": ["Profile"],
      "name": "Jobs for the Future (JFF)",
      "url": "https://www.jff.org/",
      "image": "https://w3c-ccg.github.io/vc-ed/plugfest-1-2022/images/JFF_LogoLockup.png"
    },
    "credentialSubject": {
      "type": ["AchievementSubject"],
      "achievement": {
        "id": "https://example.com/achievements/21st-century-skills/teamwork",
        "type": ["Achievement"],
        "criteria": {
          "narrative": "Team members are nominated for this badge by their peers and recognized upon review by Example Corp management."
        },
        "description": "This badge recognizes the development of the capacity to collaborate within a group environment.",
        "name": "Teamwork"
      }
    },
    "credentialSchema": [
      {
        "id": "https://purl.imsglobal.org/spec/ob/v3p0/schema/json/ob_v3p0_achievementcredential_schema.json",
        "type": "1EdTechJsonSchemaValidator2019"
      }
    ]
  },
  "mapping": {
    "id": "<uuid>",
    "issuer": { "id": "<issuerDid>" },
    "credentialSubject": { "id": "<subjectDid>" },
    "validFrom": "<timestamp>",
    "validUntil": "<timestamp-in:365d>"
  }
}'

Path Parameters

  • orgID: String (required) - Your organization ID, e.g. test.enterprise-sandbox.waltid.dev.
  • target: String (required) - The issuer service path followed by the new profile's own ID as the final segment, {organizationID}.{tenantID}.{issuerServiceID}.{profileId}, e.g. waltid.tenant1.issuer1.profile-abc123. The {profileId} you choose here becomes the profile's ID.

Header Parameters

  • Authorization: String (required) - Bearer token for Enterprise Stack authentication. Format: Bearer {token}.

Body Parameters

  • name: String (required) - A human-readable name for the profile.
  • credentialConfigurationId: String (required) - The credential configuration ID this profile issues. Must match a credential configuration declared on your issuer service.
  • issuerKeyId: resourceIdentifier (required) - The key ID of a key stored in a KMS service under the same tenant, e.g. waltid.tenant1.kms1.key1.
  • credentialData: Object (required) - The credential data template. Structure depends on the credential format.
  • issuerDid: String (optional) - The DID of the issuer. Not supported for mDocs.
  • x5Chain: Array (optional) - X.509 certificate chain for signing (required for mDoc). The first certificate is the issuer's; provide the full chain if required. Each entry is a descriptor object { "type": "pem-encoded-x509-certificate-descriptor", "pemEncodedCertificate": "<PEM>" }. (A bare PEM string is also accepted for backwards compatibility, but the API always stores and returns the object form.)
  • mapping: Object (optional) - Data mapping with data functions for dynamic value insertion at claim time.
  • selectiveDisclosure: Object (optional) - Which SD-JWT claims a holder can selectively disclose, plus optional decoy configuration. Applies to SD-JWT VC and W3C SD-JWT credentials.
  • idTokenClaimsMapping: Object (optional) - Maps claims from external IdP tokens to credential data fields using JSONPath. See ID Token Claims Mapping.
  • mDocNameSpacesDataMappingConfig: Object (optional) - Type conversion configuration for mDoc credentials. See mDoc Data Mapping.
  • authorizedTransactionDataTypes: Array of Strings (optional) - OpenID4VP transaction-data types this mDoc's device key may sign. Embedded in the MSO as KeyAuthorizations at issuance. See Authorized Transaction Data Types.
  • credentialStatus: Object (optional) - Configuration for credential status (revocation/suspension). See Credential Status.
  • notifications: Object (optional) - Webhook notification settings. See Notifications.
  • w3cVersion: String (optional) - W3C data model version of the issued credential. Either W3CV11 for VCDM v1.1 or W3CV2 for v2.

    The w3cVersion parameter controls the format of the issued credential. When set to W3CV2, the service automatically applies the correct VCDM v2 @context (https://www.w3.org/ns/credentials/v2) and uses validFrom/validUntil in place of issuanceDate/expirationDate, regardless of what is provided in credentialData.


Example Response
{
  "profileId": "profile-abc123",
  "name": "Open Badge Credential Profile",
  "version": 1,
  "credentialConfigurationId": "OpenBadgeCredential_jwt_vc_json",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "issuerDid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
  "credentialData": { "...": "..." },
  "mapping": { "...": "..." },
  "w3cVersion": "W3CV2",
  "createdAt": 1704067200000,
  "updatedAt": 1704067200000
}

The service stores and echoes the full profile object; credentialData and mapping are elided above for brevity. Format-specific fields are included when set — w3cVersion for W3C, selectiveDisclosure for SD-JWT VC, mDocNameSpacesDataMappingConfig / authorizedTransactionDataTypes for mDoc.

Response Fields

  • profileId: String - The profile's own ID — the last path segment you chose, e.g. profile-abc123. To address the profile elsewhere (e.g. as an offer target), use the full path {target}.{profileId}.
  • version: Integer - The profile version (starts at 1, increments on update).
  • createdAt / updatedAt: Long - Unix timestamps (ms).

Response Codes

  • 201 — Profile created successfully.
  • 400 — Invalid request body.
  • 401 — Invalid or missing authentication token.

🎉 You've created a credential profile.


Advanced Configuration

ID Token Claims Mapping

When using the authorization code flow with an external IdP, you can map claims from the ID token to credential data fields:

{
  "idTokenClaimsMapping": {
    "$.family_name": "$.credentialSubject.familyName",
    "$.given_name": "$.credentialSubject.givenName",
    "$.email": "$.credentialSubject.email"
  }
}

The keys are JSONPath expressions pointing to claims in the ID token, and the values are JSONPath expressions pointing to fields in the credential data.

mDoc Data Mapping

For mDoc/mDL credentials, you need to specify type conversions for CBOR encoding:

{
  "mDocNameSpacesDataMappingConfig": {
    "org.iso.18013.5.1": {
      "entriesConfigMap": {
        "birth_date": { "type": "string", "conversionType": "stringToFullDate" },
        "issue_date": { "type": "string", "conversionType": "stringToFullDate" },
        "expiry_date": { "type": "string", "conversionType": "stringToFullDate" },
        "portrait": { "type": "string", "conversionType": "base64StringToByteString" }
      }
    }
  }
}

Available Conversion Types:

Conversion TypeDescription
stringToFullDateConverts ISO date string (e.g. 2024-01-15) to CBOR full-date (tag 1004).
stringToTDateConverts ISO timestamp string to CBOR tdate (tag 0).
base64StringToByteStringConverts standard base64-encoded string to CBOR byte string.
base64UrlStringToByteStringConverts base64url-encoded string to CBOR byte string.

Authorized Transaction Data Types

For mso_mdoc credentials that must later present OpenID4VP transaction_data, the device key can only device-sign types that appear in the MSO's KeyAuthorizations. Issuer2 embeds that grant from authorizedTransactionDataTypes.

{
  "authorizedTransactionDataTypes": ["urn:eudi:sca:payment:1"]
}

What the issuer writes into the MSO for each listed type:

  • Namespace = the transaction-data type string itself (walt.id convention, matching what the wallet presenter emits)
  • Data elements = transaction_data_hash and transaction_data_hash_alg
  • No blanket nameSpaces authorization — only those hash elements are granted

Blank entries are dropped, duplicates collapsed. If the list is null or empty after filtering, no KeyAuthorizations are emitted.

Presentation of an unlisted type is rejected for that mDoc. Register the same type in transaction-data-profiles.conf, and list it here on the issuing profile.

This field applies to mDoc (mso_mdoc) only. SD-JWT VC transaction-data binding uses the KB-JWT and does not consume authorizedTransactionDataTypes.

Example — mDoc profile that authorizes EUDI TS-12 SCA payment transaction data:

{
  "name": "SCA Payment Card Profile",
  "credentialConfigurationId": "eu.europa.ec.eudi.sca.payment_card.1",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "x5Chain": [
    {
      "type": "pem-encoded-x509-certificate-descriptor",
      "pemEncodedCertificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n"
    }
  ],
  "credentialData": {
    "eu.europa.ec.eudi.sca.payment_card.1": {
      "card_scheme": "visa",
      "card_last4": "4242",
      "card_holder_name": "Jane Doe"
    }
  },
  "authorizedTransactionDataTypes": ["urn:eudi:sca:payment:1"]
}

Credential Status

Configure credential status for revocation/suspension support:

{
  "credentialStatus": {
    "statusCredentialConfig": "waltid.tenant1.credentialstatus.config1",
    "initialStatus": "0x0"
  }
}
  • statusCredentialConfig: resourceIdentifier - Reference to a credential status configuration in the Credential Status Service.
  • initialStatus: String - Initial status value (e.g. "0x0" for valid).

To use credentialStatus, make sure the credential status service is added as a dependency of the Issuer2 service.

Different credential formats support different status list types:

  • W3C JWT/SD-JWT: Bitstring Status List, StatusList2021
  • SD-JWT VC (IETF): Token Status List
  • mDoc: Token Status List

Automatic rollover: If the referenced credential status service has autoRollover enabled, new status lists are created automatically when capacity thresholds are reached. This is transparent to the issuer — you can keep using the same statusCredentialConfig reference. Learn more about automatic rollover.


Example Profiles

SD-JWT VC Profile

{
  "name": "Identity Credential Profile",
  "credentialConfigurationId": "identity_credential_vc+sd-jwt",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "issuerDid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
  "credentialData": {
    "given_name": "John",
    "family_name": "Doe",
    "birthdate": "1990-01-15"
  },
  "selectiveDisclosure": {
    "fields": {
      "birthdate": { "sd": true }
    }
  },
  "mapping": {
    "iat": "<timestamp-seconds>",
    "exp": "<timestamp-in-seconds:365d>"
  }
}

mDoc Profile with PEM X.509 Certificate

{
  "name": "Photo ID Profile",
  "credentialConfigurationId": "org.iso.23220.photoid.1",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "x5Chain": [
    {
      "type": "pem-encoded-x509-certificate-descriptor",
      "pemEncodedCertificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n"
    }
  ],
  "credentialData": {
    "org.iso.23220.photoid.1": {
      "given_name_unicode": "John",
      "family_name_unicode": "Doe",
      "birth_date": "1990-01-15",
      "issuance_date": "2024-01-01",
      "expiry_date": "2029-01-01",
      "portrait": "base64-encoded-image-data"
    }
  },
  "mDocNameSpacesDataMappingConfig": {
    "org.iso.23220.photoid.1": {
      "entriesConfigMap": {
        "birth_date": { "type": "string", "conversionType": "stringToFullDate" },
        "issuance_date": { "type": "string", "conversionType": "stringToFullDate" },
        "expiry_date": { "type": "string", "conversionType": "stringToFullDate" },
        "portrait": { "type": "string", "conversionType": "base64StringToByteString" }
      }
    }
  }
}

mDoc Profile with X.509 Store Stored Certificate

{
  "name": "Photo ID Profile",
  "credentialConfigurationId": "org.iso.23220.photoid.1",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "x5Chain": [
    {
      "type": "x509-store-stored-certificate-descriptor",
      "storedCertificateId": "waltid.tenant1.x509-store.issuer-certificate"
    }
  ],
  "credentialData": {
    "org.iso.23220.photoid.1": {
      "given_name_unicode": "John",
      "family_name_unicode": "Doe",
      "birth_date": "1990-01-15",
      "issuance_date": "2024-01-01",
      "expiry_date": "2029-01-01",
      "portrait": "base64-encoded-image-data"
    }
  },
  "mDocNameSpacesDataMappingConfig": {
    "org.iso.23220.photoid.1": {
      "entriesConfigMap": {
        "birth_date": { "type": "string", "conversionType": "stringToFullDate" },
        "issuance_date": { "type": "string", "conversionType": "stringToFullDate" },
        "expiry_date": { "type": "string", "conversionType": "stringToFullDate" },
        "portrait": { "type": "string", "conversionType": "base64StringToByteString" }
      }
    }
  }
}

Profile with Notifications

{
  "name": "Notified Credential Profile",
  "credentialConfigurationId": "OpenBadgeCredential_jwt_vc_json",
  "issuerKeyId": "waltid.tenant1.kms1.key1",
  "issuerDid": "did:key:z6MkjoRhq1jSNJdLiruSXrFFxagqrztZaXHqHGUTKJbcNywp",
  "credentialData": { "...": "..." },
  "notifications": {
    "webhook": {
      "url": "https://your-server.com/webhook/issuance",
      "bearerToken": "your-secret-token"
    }
  }
}

Next Steps

Last updated on August 18, 2026