Getting started
This mirrors the automated acceptance test (ApiFirstAcceptanceTests), so every step here is a step the
platform is actually tested to support.
export DILIGENCE_BASE_URL="https://your-diligenceid-host"
export DILIGENCE_API_KEY="did_test.ak_example_0000.<secret>"
1. Get a sandbox and a key
An administrator or tenant owner provisions your sandbox once:
POST /api/sandbox
{
"data": {
"environment": { "environmentId": "env_...", "environmentType": "Sandbox", "status": "Active" },
"apiClient": { "clientId": "ak_...", "environment": "Sandbox", "keyPrefix": "did_test" },
"apiKey": "did_test.ak_....<secret>",
"environmentCreated": true
}
}
Copy apiKey now. It is returned exactly once and cannot be recovered — not by support, not by an
administrator, not by any endpoint. Calling POST /api/sandbox again returns the same environment but mints
a new key; the previous one keeps working until it is revoked.
The key is scoped to the whole developer lifecycle — organisations, issuers, credential configurations, issuance, verification policies, verification — and deliberately cannot manage API clients, the platform or tenant configuration.
Everything from here uses /v1 and that key alone.
2. Confirm the key works
curl -sS "$DILIGENCE_BASE_URL/v1/issuers" -H "Authorization: ApiKey $DILIGENCE_API_KEY"
200 means authenticated and scoped. 401 means the key is not valid. 403 means it is valid but lacks the
scope for that call.
A Sandbox key sees only Sandbox resources. A Production issuer is not merely forbidden to it — it is reported as not found, because confirming that it exists would itself be a disclosure.
3. Create an issuer
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/issuers" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"displayName": "Acme Workforce",
"organisationReference": "acme-ltd",
"issuerType": "Root",
"configuration": {
"canonicalIssuerUri": "https://issuer.acme.example",
"publicMetadataUri": "https://issuer.acme.example/.well-known/openid-credential-issuer",
"trustProfileVersion": "RootTrustProvider:Test",
"statusMechanism": "StatusList"
},
"signingKey": { "algorithm": "ES256", "provider": "Software" }
}'
Scope: issuers.manage. Returns 201 with the issuer in Draft.
The issuer is created in your key's environment — a Sandbox key cannot create a Production issuer, whatever
the request body says. configuration and signingKey are optional here; omit them and use
PATCH /v1/issuers/{issuerId} instead. Both routes run identical validation, because both call the same
service Diligence Admin does.
Create the organisation first if you do not have one — POST /v1/organisations, scope organisations.manage.
4. Create a credential configuration
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/credential-configurations" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"issuerId": "iss_example",
"identifier": "employee-badge",
"displayName": "Employee badge",
"schemaId": "schema_employee_badge",
"claims": [
{ "name": "employee_id", "displayName": "Employee ID", "dataType": "String",
"required": true, "selectiveDisclosureAllowed": true, "displayOrder": 0 }
]
}'
Scope: credential-configurations.manage. Creates the configuration, activates its first version and
authorises the issuer to use it, in one call. The configuration inherits the issuer's environment, which is
what stops a Sandbox configuration ever referencing a Production issuer.
dc+sd-jwt and ES256 are the platform's current format and algorithm limits, not overridable defaults.
5. Check readiness, then activate
curl -sS "$DILIGENCE_BASE_URL/v1/issuers/$ISSUER_ID/readiness" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY"
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/issuers/$ISSUER_ID/activate" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY"
readyForActivation is the summary; required is the itemised checklist, each entry naming a code, whether
it is satisfied and a detail. Activation runs the same checklist and returns 409 listing what is
outstanding rather than activating a half-configured issuer.
6. Issue
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/credentials/issuance" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"issuerId": "iss_example",
"credentialConfiguration": "cfg_example",
"externalSubjectReference": "employee-4821",
"claims": { "subject_identifier": "employee-4821" }
}'
201 returns a transactionId and a credentialOfferUri; the status is awaiting_wallet until the holder
accepts. issuerId is required — an API key belongs to a tenant, not to one issuer.
Always send Idempotency-Key. Without it, a timeout you retry can issue two credentials.
7. Define what you want to verify
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/verification-policies" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"policyIdentifier": "verified-employee",
"displayName": "Verified employee",
"organisationReference": "acme-ltd",
"credentialConfigurations": ["ccr_example"]
}'
A policy is created and activated in one call. Pass "activate": false to leave it Draft — a Draft policy
cannot start a verification. suspend and reactivate are available on the same resource.
8. Verify
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/verifications" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "policy": "verified-employee" }'
201 returns a verification id, a presentationUrl and a qrCodePayload. You name a policy; DiligenceID
builds the OpenID4VP request, so you never construct protocol parameters.
Poll GET /v1/verifications/{id} — or better, subscribe to webhooks. status moves from
pending through to verified, rejected, expired or cancelled.
Starting a verification against a suspended policy returns 400. That is the policy lifecycle working, not
a malformed request.
9. Revoke
curl -sS -X POST "$DILIGENCE_BASE_URL/v1/credentials/$CREDENTIAL_ID/revoke" \
-H "Authorization: ApiKey $DILIGENCE_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "reason": "Employment ended" }'
Immediate and not reversible. A later verification against a policy requiring an active status will fail.
Run it end to end
examples/quickstart/ contains the same sequence as numbered scripts:
cd developer-docs/examples/quickstart
export DILIGENCE_BASE_URL="https://your-diligenceid-host"
export DILIGENCE_API_KEY="did_test...."
export ISSUER_ID="iss_..."
./run-all.sh