Custodial vs Non-Custodial Mode
Before you pick endpoints, decide which operating mode you are integrating against. The mode changes one thing: who plays the Holder role. Everything else — Issuer flow, Verifier flow, governance, standards — is identical.
Most TCS deployments run in custodial mode, and we recommend it for most integrators. Holder Service was built precisely because most products integrating digital identity wallets need a convenient cloud wallet service — picking custodial means you get one without writing OID4VCI/OID4VP yourself. If you are unsure which mode you need, pick custodial.
The one-sentence difference
Section titled “The one-sentence difference”| Mode | Who plays the Holder | What you call |
|---|---|---|
| Custodial | TCS Holder Service — a hosted wallet exposed as REST API | Issuer Service + Holder Service + Verifier Service |
| Non-Custodial | The end user’s own wallet app (any OID4VCI/OID4VP-conformant wallet) | Issuer Service + Verifier Service. The wallet sits on the user’s device — you do not call it. |
In custodial mode your backend orchestrates all three IHV roles through TCS APIs. In non-custodial mode it orchestrates two (Issuer, Verifier); the Holder lives on the user’s device and reaches TCS over deep-link / QR.
Quick Start walks through custodial mode end-to-end. If that’s where you’re heading, skim this page for the model and skip ahead — you can come back when you need the contrast.
Holder Service is a hosted wallet, not a wallet SDK
Section titled “Holder Service is a hosted wallet, not a wallet SDK”The single most important concept in custodial mode is this:
Holder Service = a TCS-managed wallet exposed as a REST API.
It is not a library you embed and not a UI you redirect to. It is an HTTP service that, on behalf of your end users, performs every wallet-side operation a wallet would normally do on a phone:
- Holds end-user accounts and keypairs
- Parses issuer offers and verifier authorization requests
- Builds proof JWTs and key-binding JWTs
- Selects which disclosures to reveal
- Calls Credential Issuer / Verifier Service with the right payloads
- Stores received credentials and lets you list / get / delete them
Your backend acts on the user’s behalf by holding a per-user JWT (issued by Holder Service at login) and calling /v1/oid4vci/*, /v1/oid4vp/*, /v1/did/*, /v1/vc/*. You do not handcraft any OID4VCI / OID4VP payload yourself.
In non-custodial mode this entire surface goes away. The user’s wallet does the same work locally and talks to Issuer Service + Verifier Service directly.
Topology
Section titled “Topology”Custodial mode Non-Custodial mode───────────────── ─────────────────[Your Backend] [Your Backend] │ │ ├──► Issuer Service (POST /v1/offers) ├──► Issuer Service (POST /v1/offers) ├──► Holder Service (full wallet API) │ ↓ delivers offer link via QR / deep-link └──► Verifier Service (auth-request / result) │ ├──► Verifier Service (auth-request / result) │ ↓ delivers request link via QR / deep-link ▼ [User's Wallet App] on the end user's device (any OID4VCI/OID4VP-conformant wallet)Both modes share the same governance fabric — Trust Registry and Schema Registry — and the same wire format (SD-JWT VC with dc+sd-jwt).
Why TCS provides Holder Service
Section titled “Why TCS provides Holder Service”Most systems integrating digital identity wallets need a convenient wallet service — somewhere credentials live, somewhere protocol details get handled, somewhere users’ wallets can be managed at scale via API. Few teams want to build that themselves; even fewer want to maintain it.
Holder Service is that service. It is a general-purpose cloud wallet management API: any product that needs verifiable-credential wallet capability can use it without taking on the OID4VCI / OID4VP burden. It is not “the holder side of TCS issuance” — it is a stand-alone wallet service that happens to be co-deployed with the issuance and verification surfaces.
Even when end users already have a wallet on their phone, Holder Service is still the convenient surface for credentials issued through your product — the user does not have to install yet another wallet, and your product retains a clean API for listing, presenting, and revoking those credentials.
If you’ve ever asked “where do my users’ verifiable credentials live, and how do I make presenting them painless?” — that is what Holder Service is for.
What you build on each side
Section titled “What you build on each side”| Concern | Custodial mode | Non-Custodial mode |
|---|---|---|
| End-user accounts | You register users via POST /v1/user/register on Holder Service | The wallet app handles its own accounts |
| Holder DID + keypair | You create per-user DIDs via POST /v1/did on Holder Service. You store the returned private key. | Wallet generates and keeps its own keys |
| Receiving a credential | Your backend calls POST /v1/oid4vci/receive with the offer URI + holder DID + private key | Wallet exchanges code, builds proof JWT, calls /credential itself |
| Listing / managing credentials | Your backend calls GET /v1/vc, DELETE /v1/vc/:id | Wallet shows and stores them locally |
| Presenting a credential | Your backend calls POST /v1/oid4vp/request-details then POST /v1/oid4vp/presentation | Wallet builds the VP token and key-binding JWT itself |
| Wallet UI | You build the consent / selection screens in your product | The user’s wallet app already has them |
Where holder keys live
Section titled “Where holder keys live”Holder Service does not persist holder private keys. The keypair is returned exactly once at DID creation time, used for the request, then discarded server-side. This is a security feature, not a friction — the keys never sit in TCS infrastructure, only in your secret manager / KMS, exactly like any other per-user secret in your product (a session-signing key, a tenant API token, an encrypted attribute).
In practice that means:
- Save each end-user’s DID private key when
POST /v1/didreturns it. Treat it the same as any per-user secret — secret manager, KMS, or an encrypted column. Pass it back to Holder Service on every/v1/oid4vci/receiveand/v1/oid4vp/presentationcall. - The Holder Service JWT issued at login is a per-user session token.
- End-user identity. Holder Service stores accounts but never sees email or PII unless you supply them.
You do not construct, sign, or verify any cryptographic payload yourself. Holder Service does all crypto with the key you pass in at request time and discards it after the request.
The result: TCS, your product, and the end user each see only what they need. Verifiable credentials and key material live where they should — and that’s a property of the design, not something you have to enforce yourself.
When to choose which
Section titled “When to choose which”Choose custodial mode (recommended) when:
- You’re integrating digital identity wallets into a product and want a service that handles wallet-side mechanics for you. Most teams land here.
- End users don’t already have a digital wallet — and aren’t going to install one.
- You want one integration surface, one ops footprint, and credentials your product can list / audit / recover via API.
- Even when end users have other wallets — Holder Service still works as a clean cloud surface for credentials issued through your product.
Choose non-custodial mode when:
- You’ve already built or integrated an OID4VCI / OID4VP wallet on your side, and adding Holder Service would duplicate work you’ve already done.
- Your target users live on an established digital-wallet ecosystem (HAIP-conformant wallets, EUDI Wallet, government identity wallets) and you’re plugging into that ecosystem rather than building inside your product.
- You’re shipping a wallet app yourself and TCS is just the issuance / verification edge.
In short: the typical reason to pick non-custodial is you already know OID4VCI / OID4VP and have a wallet implementation you want to keep using. Otherwise, Holder Service almost always saves you work.
The two modes can coexist on the same TCS deployment for different tenants — the choice does not lock the platform. If you’re unsure: pick custodial, ship faster, run a non-custodial tenant later if a specific user case demands.
How the rest of the docs are structured
Section titled “How the rest of the docs are structured”The Development guides are written custodial-first:
- Issuer · Issue Credential — your backend → TCS Issuer Service.
- Holder · Manage Wallets & Credentials — your backend → TCS Holder Service. This is the page that does not exist in non-custodial mode.
- Verifier · Verify Credential — your backend → TCS Verifier Service.
- Non-Custodial Mode — what changes if the Holder is an external wallet, plus the wallet-protocol detail (proof JWT, key-binding JWT, sd_hash) you need when integrating with one or building one.
If you are running custodial mode you can skip Non-Custodial Mode entirely — it has no impact on your integration.
What’s next
Section titled “What’s next”- Thinking in IHV Model — the role mental model that the mode-choice sits on top of.
- Quick Start — a 5-minute end-to-end run in custodial mode.
- Holder · Manage Wallets & Credentials — the core integration surface for custodial deployments.