Sandbox onboarding
The current DLBR EID sandbox is the isolated staging environment. It uses the same API contract as production, but has separate Worker bindings, D1 databases, queues, trust configuration, and API keys. Sandbox keys are prefixed with sk_test_; production keys are prefixed with sk_live_.
When creating scoped keys through the API, pass a future ISO-8601 expires_at for CI or temporary integrations. Omit it (or use null) only for a deliberately non-expiring key governed by your enterprise key policy.
The local synthetic environment is a developer-only test lane. It uses synthetic certificates and the mock wallet and must not be treated as evidence of production wallet interoperability.
1. Choose the environment
| Environment | Gateway mode | Key prefix | Data | Typical use |
|---|---|---|---|---|
| Local synthetic | test | sk_test_ | Local D1/DO state | Unit and integration development |
| Staging sandbox | test | sk_test_ | Remote staging bindings | Team QA and wallet testing |
| Production | live | sk_live_ | Production bindings | Real customer verification |
Never point a sk_test_ key at a live base URL or a sk_live_ key at staging. The SDK validates the explicit mode/key pair, and the Gateway validates the key mode at request time.
2. Provision a staging key
An operator provisions a tenant key from the Gateway workspace. The plaintext key is printed once; store it in the team's secret manager immediately.
cd apps/gateway
pnpm run provision:client -- \
--client-id acme-bank \
--allowed-origins https://sandbox.acme.example \
--env staging \
--remoteThe command writes only the key hash to the staging D1 database and prints a one-time sk_test_... key. Add the key to the sandbox service secret store, never to source control.
For a local synthetic tenant, omit --remote and use --env synthetic after applying the synthetic migrations. The synthetic lane is intentionally separate from the shared staging sandbox.
3. Configure the SDK
import { DlbrId } from "@dlbr/eid-sdk";
const id = new DlbrId({
baseUrl: process.env.DLBR_ID_BASE_URL!,
apiKey: process.env.DLBR_ID_API_KEY!,
mode: "test",
apiVersion: "2026-09-21",
});
const session = await id.sessions.create({
credentials: [{
format: "mso_mdoc",
issuer_id: "https://issuer.example",
namespace: "org.iso.18013.5.1",
claims: ["given_name"],
}],
});
if (session.livemode) throw new Error("Sandbox configuration resolved to live mode");
console.log(session.qr_code_url);The Gateway returns livemode: false for sandbox sessions. Treat a mismatch as a deployment/configuration error and stop the flow.
4. Validate the sandbox flow
For a real staging wallet test, the tenant must also have the required relying-party registration and trust material provisioned. Use the EUDI integration checklist before debugging SDK calls.
For a synthetic protocol smoke test, run the format-specific Gateway scripts from apps/gateway:
STAGING_URL=https://id-staging.dlbr.workers.dev \
STAGING_API_KEY=sk_test_... \
pnpm run smoke:mdoc-stagingThe synthetic smoke scripts validate the protocol path; they do not replace a real EUDI Wallet test.
5. Promote to production
Create a separate production tenant key only after production relying-party registration, trust configuration, and secret contracts are complete:
cd apps/gateway
pnpm run provision:client -- \
--client-id acme-bank \
--allowed-origins https://app.acme.example \
--remoteThe production command defaults to the production D1 database and emits an sk_live_... key. Configure the production SDK with mode: "live" and an HTTPS base URL. Do not reuse the staging key, webhook secret, or client database records.
Key hygiene
- Store keys in a secret manager and expose them only to trusted server code.
- Rotate a compromised key immediately with
id.apiKeys.rotate(keyId)or the operator workflow. - Revoke old keys and verify that the old credential returns
401. - Keep test and live webhook signing secrets separate.
- Never put API keys in
NEXT_PUBLIC_*, browser bundles, URLs, logs, or support tickets.