{"templateId":"markdown","sharedDataIds":{},"props":{"metadata":{"markdoc":{"tagList":[]},"type":"markdown"},"seo":{"title":"Changelog"},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"changelog","__idx":0},"children":["Changelog"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["All notable changes to the DeepCredentials B2B API."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v220--2026-08-18","__idx":1},"children":["v2.2.0 — 2026-08-18"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added","__idx":2},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Credential Invitations API"]}," — Service users can create, list, get, rotate, and revoke invitations under ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/b2b/v1/credential-invitations"]},". Create and rotate return the one-time plaintext code; list, get, and revoke expose code-free metadata."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_invitation.status_changed"]}," webhook"]}," — An opt-in terminal event for invitation ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["redeemed"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["expired"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["revoked"]}," transitions. The slim payload contains ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["invitation_id"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]},", and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["offer_id"]}," only after redemption. Existing webhook configurations must enable the event in the portal."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"changed","__idx":3},"children":["Changed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Partner-owned invitation delivery"]}," — DeepCredentials does not email codes created or rotated through the B2B invitation API. The partner owns how it delivers the code and presents the redemption experience; its backend can exchange the recipient's email and code through the public redemption endpoint."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Progress callbacks clarified"]}," — Verification, invitation, and issuance webhooks are slim hints followed by authenticated B2B GET reconciliation. Webhook delivery currently makes one synchronous attempt and can be missed."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["reference_id"]}," clarified"]}," — The field is optional correlation metadata only; it does not provide idempotency, uniqueness, or response caching."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v210--2026-06-09","__idx":4},"children":["v2.1.0 — 2026-06-09"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"breaking","__idx":5},"children":["Breaking"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["template_id"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_definition_id"]}]}," — B2B request bodies and query parameters that previously accepted ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["template_id"]}," now require ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_definition_id"]},". Applies to ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/verification-sessions"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/credential-offers"]},", and the list query filters on those resources."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["template"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_definition"]}," in responses"]}," — The top-level response object previously named ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["template"]}," is now named ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_definition"]},". Inner fields (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["id"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["vct"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["name"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["has_logo"]},") are unchanged. Terminology throughout the API is now \"Credential Definition\" rather than \"Template\"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added-1","__idx":6},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/credential-definitions"]}]}," — Returns the credential definitions available to your organization. Any authenticated service user can call this endpoint (no additional scope required beyond a valid token with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Org-Id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Environment"]},")."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"docs","__idx":7},"children":["Docs"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["\"Open in API reference\" deep-links"]}," — Every code sample in the guides now has an immediate deep-link to the matching operation in the rendered API reference."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Broadened intro"]}," — The home page and Quickstart now cover all three API pillars: verification, issuance, and self-service."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v200--2026-05-22","__idx":8},"children":["v2.0.0 — 2026-05-22"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"breaking-1","__idx":9},"children":["Breaking"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Portal-issued credentials retired."]}," API keys and OAuth clients minted in the DeepCredentials portal no longer work. Authentication now uses ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["DeepAdmin service users"]}," authenticated against the DeepCloud SSO realm with the OAuth 2.0 Resource Owner Password Credentials grant. See the new ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/guides/authentication/service-users"},"children":["Service Users"]}," guide."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/oauth/token"]}," removed."]}," Exchange credentials directly with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST <keycloak-realm>/protocol/openid-connect/token"]}," against ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deepcloud.swiss"]}," (prod) or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["int.deepcloud.swiss"]}," (test)."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Org-Id"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Environment"]}," headers are now required on every ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/b2b/v1/*"]}," request."]}," ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Org-Id"]}," is the UUID of the organization the service user is a member of; ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Environment"]}," is ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["beta"]}," or ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["production"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["X-Api-Key"]}," header is no longer accepted."]}," Authenticate exclusively with ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authorization: Bearer <access_token>"]}," from the DeepCloud SSO token endpoint."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"removed","__idx":10},"children":["Removed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["API Keys and OAuth Clients management surfaces in the DeepCredentials portal."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Authentication API"]}," OpenAPI spec (the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["/b2b/v1/oauth/token"]}," operation is gone)."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v140--2026-05-22","__idx":11},"children":["v1.4.0 — 2026-05-22"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"changed-1","__idx":12},"children":["Changed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Scope strings renamed"]}," — B2B scopes are now namespaced under ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deepcredentials.*"]},":"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["issuance"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deepcredentials.issue"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["verification"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deepcredentials.verify"]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service"]}," → ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["deepcredentials.self-service"]}]}]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Provision new credentials with the namespaced names. Enforcement will roll out together with the matching DeepAdmin update; until then, in-flight tokens carrying the legacy names continue to work."]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v130--2026-05-20","__idx":13},"children":["v1.3.0 — 2026-05-20"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added-2","__idx":14},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["identification_filled"]}," claim source"]}," — Self-service configs can now mark a template claim as automatically pre-filled from the identification provider's verified attributes. Tenants configure the per-claim mapping in the portal (no B2B API surface). The webhook decision flow benefits passively: by the time ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.submitted"]}," fires, the snapshot's ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["claims"]}," field already reflects the merged result (user → identification → admin), so an empty ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_claims"]}," approve issues a credential carrying the identification-derived values."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["editable_field_sources"]}," enum extended"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/self-service/requests/{id}"]}," may now return ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"identification_filled\""]}," alongside ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"user_filled\""]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["\"admin_filled\""]},". See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/guides/self-service/flow#overriding-user-supplied-claims"},"children":["Self-Service Flow guide"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v120--2026-05-19","__idx":15},"children":["v1.2.0 — 2026-05-19"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added-3","__idx":16},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Credential validity"]}," — Credentials are now issued with a tenant-controlled ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["exp"]}," claim. Set a default on the credential template (portal → Templates) and override per-issuance via the new optional ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["validity_seconds"]}," field on ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/credential-offers"]},". Send no value to inherit the template default; the credential is issued without an ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["exp"]}," claim (never expires) only when both the template default and request override are absent. Self-service configs always carry their own explicit validity (or explicit \"never expires\") chosen at config creation. Allowed range: 60 seconds to 10 years. Issued-credential responses (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/issued-credentials/{id}"]},", list, and webhook payload-fetch) now include ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valid_from"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valid_until"]}," so you can show expiry in your UI and react before a credential lapses."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Self-service request snapshot — full claim schema"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/self-service/requests/{requestId}"]}," now returns ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["editable_fields"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["editable_field_types"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["editable_field_sources"]}," describing every claim on the template (not just admin-filled ones). Enables rendering a \"review & override\" form without a second template fetch. See the ",{"$$mdtype":"Tag","name":"MarkdownLink","attributes":{"href":"/docs/guides/self-service/flow#overriding-user-supplied-claims"},"children":["Self-Service Flow guide"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"changed-2","__idx":17},"children":["Changed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Issued credential status semantics"]}," — The ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]}," field (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["active"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["suspended"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["revoked"]},") is the ",{"$$mdtype":"Tag","name":"em","attributes":{},"children":["revocation"]}," lifecycle (driven by the status list). Expiration is now expressed separately via ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valid_until"]},". A credential can be ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["active"]}," and past its ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["valid_until"]}," simultaneously — wallets and verifiers reject it on the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["exp"]}," claim; we don't automatically flip its ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["status"]},"."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_claims"]}," may override user-supplied claims"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/self-service/requests/{requestId}/decision"]}," already accepted any template claim key in the ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_claims"]}," payload; the contract is now explicit: when a key appears in both the user submission and your ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_claims"]},", your value wins and is the one stamped on the credential. ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_filled_*"]}," continues to describe the ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["required"]}," contract only."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v110--2026-05-16","__idx":18},"children":["v1.1.0 — 2026-05-16"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added-4","__idx":19},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Self-Service API"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/self-service/requests/{requestId}"]}," returns the full request snapshot (status, captured claims, identification result, offer id, timestamps, ",{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["plus the admin-claims schema"]}," — ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_filled_fields"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_filled_types"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_filled_required"]},", mirroring how verification ships ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["requested_fields"]}," + ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credential_subject_types"]}," so the tenant can dynamically render or validate ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["admin_claims"]}," without hard-coded template knowledge). ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/self-service/requests/{requestId}/decision"]}," approves or rejects an end-user-initiated request — required for tenants whose configs run in ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook"]}," verification mode."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Self-service webhook events"]}," — Six events covering the full lifecycle:",{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.submitted"]}," — fires for ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["webhook"]},"-mode configs when a request is ready for a decision."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.approved"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.rejected"]}," — fire for all verification modes so you have an audit trail of every decision."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.credential_issued"]}," — terminal success; the wallet accepted the credential."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.offer_expired"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service.request.failed"]}," — terminal post-approval failure paths (offer TTL exceeded, wallet rejected)."]}]}]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":[{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service"]}," scope"]}," — Required for the Self-Service API and selectable on API keys / OAuth clients in the portal."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Self-Service Flow guide"]}," — End-to-end walkthrough of the three verification modes (manual, webhook, automatic), lifecycle diagram, full user ↔ Portal ↔ tenant-backend sequence, and webhook payload contract."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Webhook subscription management"]}," — The portal webhook page now has a per-event checkbox grid grouped by family (Verification / Credential Issuance / Self-Service). Unchecked events are silently dropped at our edge — no delivery, no retry. New webhook configs default to all events on; existing configs keep their current set and have to explicitly opt in to events added in future releases."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"fixed","__idx":20},"children":["Fixed"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Scopes documentation"]}," — The scopes table previously listed ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credentials.read"]}," / ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["credentials.write"]},", which never existed. Replaced with the actual scopes: ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["verification"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["issuance"]},", ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["self_service"]},"."]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"v100--2025-03-29","__idx":21},"children":["v1.0.0 — 2025-03-29"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"added-5","__idx":22},"children":["Added"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Verification API"]}," — Create and poll OID4VP verification sessions (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST"]}," and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/verification-sessions"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authentication API"]}," — OAuth 2.0 Client Credentials token exchange (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["POST /b2b/v1/oauth/token"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Health API"]}," — Credential validation and connectivity check (",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["GET /b2b/v1/health"]},")."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Webhook Events API"]}," — OpenAPI 3.1 webhook spec for ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["verification.completed"]}," with full event schema and signature headers."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Webhooks guide"]}," — Setup, HMAC-SHA256 signature verification, and secret rotation."]},{"$$mdtype":"Tag","name":"li","attributes":{},"children":[{"$$mdtype":"Tag","name":"strong","attributes":{},"children":["Authentication methods"]}," — API keys and OAuth 2.0."]}]}]},"headings":[{"value":"Changelog","id":"changelog","depth":1},{"value":"v2.2.0 — 2026-08-18","id":"v220--2026-08-18","depth":2},{"value":"Added","id":"added","depth":3},{"value":"Changed","id":"changed","depth":3},{"value":"v2.1.0 — 2026-06-09","id":"v210--2026-06-09","depth":2},{"value":"Breaking","id":"breaking","depth":3},{"value":"Added","id":"added-1","depth":3},{"value":"Docs","id":"docs","depth":3},{"value":"v2.0.0 — 2026-05-22","id":"v200--2026-05-22","depth":2},{"value":"Breaking","id":"breaking-1","depth":3},{"value":"Removed","id":"removed","depth":3},{"value":"v1.4.0 — 2026-05-22","id":"v140--2026-05-22","depth":2},{"value":"Changed","id":"changed-1","depth":3},{"value":"v1.3.0 — 2026-05-20","id":"v130--2026-05-20","depth":2},{"value":"Added","id":"added-2","depth":3},{"value":"v1.2.0 — 2026-05-19","id":"v120--2026-05-19","depth":2},{"value":"Added","id":"added-3","depth":3},{"value":"Changed","id":"changed-2","depth":3},{"value":"v1.1.0 — 2026-05-16","id":"v110--2026-05-16","depth":2},{"value":"Added","id":"added-4","depth":3},{"value":"Fixed","id":"fixed","depth":3},{"value":"v1.0.0 — 2025-03-29","id":"v100--2025-03-29","depth":2},{"value":"Added","id":"added-5","depth":3}],"frontmatter":{"seo":{"title":"Changelog"}},"lastModified":"2026-08-19T08:56:28.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/changelog","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}