Creating DIDs and Registering Issuer & Verifier
What We Are Doing:
Creating a decentralized identifier (DID) for the Issuer and one for the Verifier.
Registering an Issuer bound to its DID so it can issue Verifiable Credentials.
Registering a Verifier bound to its DID so it can request and check credential presentations.
Why: Every credential the Issuer signs and every authorization request the Verifier sends is anchored to a DID — a portable, cryptographically verifiable identity. A wallet that receives a credential resolves the Issuer's DID to fetch the public key that proves the credential is authentic; a wallet that responds to a presentation request resolves the Verifier's DID to confirm who is asking. Creating these identities is a one-time setup step that you complete before defining schemas or issuing anything.
The service creates two DID methods: did:key (a self-contained identifier where the public key is encoded directly in the identifier) and did:web (an identifier whose DID document the service hosts for you over HTTPS). It serves the did:web documents itself — you never register or anchor a DID on any external system.
Set up your environment first. The Agent/DID, Issuer, and Verifier registration endpoints live under /agent and require a valid OIDC Bearer token carrying the admin role. This tutorial keeps a separate base URL for the Issuer and the Verifier so each call clearly targets the right service. In the current One-Click setup both point at the same deployment (one service hosts the Issuer, Verifier, and Holder APIs), though a Verifier can run under its own host in other setups — so the two variables stay distinct:
ISSUER_BASE_URL=https://your-issuer.evdi.app # your Issuer deployment
VERIFIER_BASE_URL=https://your-deployment.evdi.app # same deployment today; may be a separate host
TOKEN=<your OIDC access token> # JWT with the admin roleThese are the same base URLs you prepared in your .env during Project Setup. TOKEN here is the admin OIDC access token — the same value the deploy pages store per service as ISSUER_ACCESS_TOKEN / VERIFIER_ACCESS_TOKEN. The upcoming Deploying the Issuer and Deploying the Verifier pages show where each value comes from in the One-Click portal.
Local development: with
AUTH_DISABLED=trueyou can omit theAuthorizationheader — see Authenticating to the API.
Step 1 — Create a DID
You can create either a did:key or a did:web. A did:key requires no configuration and is ideal for getting started; a did:web produces a human-readable identifier tied to your domain whose document is resolvable at a stable HTTPS URL.
Option A — Create a did:key
POST /agent/did/key
This request takes no body and returns the new DID:
Response Body
did — the new
did:keyidentifier (an Ed25519 key encoded directly in the DID).verificationMethodIds — the verification method identifiers you can reference for signing and assertions.
Option B — Create a did:web
POST /agent/did/web
Request Body
domain (required) — the hostname that will host the DID document (for example,
issuer.example.com, optionally with a port likeissuer.example.com:8080). This must be a valid hostname, not a full URL.
Response Body
did — the created identifier, in the form
did:web:<domain>:<uuid>. The service generates the trailing UUID for you.didDocument — the full DID document the service will host. It uses an Ed25519 verification key (
Ed25519VerificationKey2018) whose public material is published aspublicKeyBase58; the same key id is referenced from bothauthenticationandassertionMethod.
The service hosts this did:web document for you. It is served, unauthenticated, at a URL derived from the DID's UUID:
The same document is also available at https://issuer.example.com/0c8f3a52-9b2e-4d31-8a7c-1f6b9e4d2a10/.well-known/did.json. When a wallet or another service resolves your did:web, this is the document it reads to obtain your public key — so no extra publishing step is required on your side.
Save the returned did. You will pass it when registering the Issuer (or Verifier) in the next steps, and it becomes the :issuerDid path segment used throughout the Issuer API.
Step 2 — Register the Issuer
A DID on its own is just an identity. To start issuing credentials you register an Issuer bound to a DID you created in Step 1. The Issuer signs every credential with that DID's key and advertises the credentials it supports through its OpenID4VCI metadata.
POST /agent/issuer
Request Body
did (required) — the DID the Issuer is bound to. It must be a DID this service already created (from Step 1).
Response Body
issuerId — the Issuer's identifier, equal to the DID you bound it to. This is the
:issuerDidpath segment you'll use when assigning schemas, creating credential offers, and signing credentials.credentialConfigurationsSupported — the credential configurations this Issuer can issue. It is built from the platform's active schemas — empty on a fresh deployment — and is refreshed when you create and assign schemas. Each schema and format combination becomes a credential configuration id of the form
Name@Version:format, such as[email protected]:sd-jwt.
The response can also carry optional display metadata (human-readable details wallets can show) when present on the issuer record.
You can fetch the Issuer record at any time with GET /agent/issuer/:did, list every registered Issuer with GET /agent/issuers, and retrieve its OpenID4VCI metadata document with GET /agent/issuer/:did/.well-known/did-configuration.
Step 3 — Register the Verifier
The verification side follows the same pattern, but runs against your Verifier ($VERIFIER_BASE_URL) — which in the current One-Click setup shares the Issuer's deployment, though it may run under its own host in other setups, with its own DIDs and admin access token. Create a DID for the Verifier there (repeat Step 1 against $VERIFIER_BASE_URL — a separate did:key or did:web is fine) and register a Verifier bound to it. The Verifier signs the authorization requests it sends to wallets with this DID, so holders can confirm who is asking for a presentation.
POST /agent/verifier
Request Body
verifierId (optional) — the Verifier's DID. If you omit it, the service generates an identifier for you; pass the DID you just created so the Verifier signs its requests with that key.
Response Body
verifierId — the Verifier's identifier. Keep it: it is the
:verifierIdpath segment you'll use when creating authorization requests later in the tutorial (Deploying the Verifier stores it in your.envasVERIFIER_ID).
You can list every registered Verifier with GET /agent/verifiers.
What you have now
You now have two cryptographic identities and the services bound to them:
An Issuer bound to its DID, ready to have schemas assigned and to issue credentials.
A Verifier bound to its DID, ready to request and check presentations.
If you created did:web identifiers, their documents are already live at /<uuid>/did.json on their respective domains, so any wallet can resolve them without further setup. Next, we'll finish setting up the Issuer deployment itself — saving its base URL and admin access token into our project's .env.
Last updated