From the open-source SDK
If you’ve integrated the open-source Self Pass frontend SDK (@selfxyz/qrcode) and backend verifier (@selfxyz/core), here’s how it maps to Self Enterprise.
Why migrate
The open-source SDK requires you to:
- Stand up an off-chain verifier yourself (or run it in-process and pay the cold-start cost).
- Manage a
ConfigStorefor predicate configurations. - Build your own webhook delivery, retry, and signature scheme.
- Write your own audit log.
- Operate it all with no SLA.
Enterprise replaces all of that with a managed service. Your frontend integration stays largely identical; the backend collapses.
Concept mapping
| Open-source self-pass | Self Enterprise |
|---|---|
SelfAppBuilder (frontend) | Same idea, but the endpoint becomes our hosted verifier, you don’t host it. |
SelfBackendVerifier | Replaced by our managed verifier. You don’t run this anymore. |
ConfigStore (your IConfigStorage impl) | Replaced by the dashboard’s flow configuration. |
| Predicate config object | A flow in the dashboard. flowId replaces inline config. |
| Per-app verifier secrets | A Bearer API key (sk_live_…). |
| Custom webhook code | A webhook endpoint you register, verified via SelfWebhooks.verify(...). |
Step-by-step
1. Map your predicate config to a flow
Today (open-source):
const verifier = new SelfBackendVerifier({
scope: 'my-app',
endpoint: 'https://myapp.com/verify',
configStore: new InMemoryConfigStorage({
minimumAge: 18,
excludedCountries: ['USA'],
ofac: true,
}),
});
With Enterprise:
- In the dashboard, create a flow.
- Configure the same rules: minimum age 18, exclude
USA, OFAC on. - Publish it. Copy the
flowIdfrom the Test or Live tab.
2. Replace SelfBackendVerifier with SelfClient
Today:
import { SelfBackendVerifier } from '@selfxyz/core';
const verifier = new SelfBackendVerifier({ /* ... */ });
app.post('/verify', async (req, res) => {
const result = await verifier.verify(
req.body.attestationId,
req.body.proof,
req.body.publicSignals,
req.body.userContextData,
);
// ...act on result
});
With Enterprise:
import { SelfClient } from '@selfxyz/enterprise-sdk';
const self = new SelfClient({ apiKey: process.env.SELF_API_KEY! });
// When the user wants to verify:
app.post('/start-verification', async (req, res) => {
const session = await self.sessions.create({
flowId: process.env.SELF_FLOW_ID!,
externalUuid: req.user.id,
});
res.json({ verificationUrl: session.verificationUrl });
});
// You no longer need a /verify endpoint, we deliver the result via webhook.
3. Replace inline verification with a webhook handler
Today your /verify endpoint runs the Groth16 verifier and acts on the result inline.
With Enterprise, register a webhook endpoint in the dashboard (it receives all events) and handle verification.completed:
import { SelfWebhooks } from '@selfxyz/enterprise-sdk';
app.post('/webhooks/self', express.raw({ type: 'application/json' }), (req, res) => {
const event = SelfWebhooks.verify(req.body, req.headers, process.env.SELF_WEBHOOK_SECRET!);
if (event.type === 'verification.completed' && event.status === 'valid') {
grantAccess(event.external_uuid, event.proof_attributes);
}
res.status(200).end();
});
external_uuid is what you passed when creating the session (typically your user ID). See Verify webhooks.
4. Drop your frontend QR component
With Enterprise you don’t render your own QR. Wherever you used @selfxyz/qrcode, call self.sessions.create(...) on your backend and redirect the user to session.verificationUrl instead; Self’s hosted page renders the QR and handles deeplinks. Then remove @selfxyz/qrcode.
5. Delete the old code paths
- Remove
@selfxyz/coreand@selfxyz/qrcode. - Remove your
ConfigStoreimplementation. - Remove your
/verifyroute, Enterprise delivers via webhook. - Remove any code that loaded verifier circuit files at boot.
What stays the same
- The Self mobile app is unchanged for your users.
- The disclosures are the same, age, nationality, OFAC, etc. See Disclosures.
- The proof system is the same under the hood.
- Your frontend gets simpler: send the user to the hosted
verificationUrl, no QR rendering required.
What’s better
- No verifier infrastructure to run.
- Audit log out of the box.
- Webhook delivery with automatic retries.
- A dashboard to change rules without a redeploy.
- Per-flow versioning, audit exactly what a user was verified against last March.
What’s different
- You pay per verification. See Plans.
- Your service no longer holds the raw proof, we verify it and hand you the attributes. (You can still read the raw proof from the
verification.completedevent if you truly need it.)
Rolling out safely
- Build the Enterprise integration behind a feature flag (
enterprise: false). - Configure a test-environment flow + webhook endpoint.
- QA against mock passports.
- Move staging to Enterprise.
- Cut over prod with a percentage rollout (10% → 50% → 100%).
- Decommission your verifier infra after a week of clean prod traffic.
Need help?
Email support@self.xyz, or your CSM if you’re on an Enterprise plan.