Skip to content

Start typing to search the documentation.

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 ConfigStore for 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-passSelf Enterprise
SelfAppBuilder (frontend)Same idea, but the endpoint becomes our hosted verifier, you don’t host it.
SelfBackendVerifierReplaced by our managed verifier. You don’t run this anymore.
ConfigStore (your IConfigStorage impl)Replaced by the dashboard’s flow configuration.
Predicate config objectA flow in the dashboard. flowId replaces inline config.
Per-app verifier secretsA Bearer API key (sk_live_…).
Custom webhook codeA 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:

  1. In the dashboard, create a flow.
  2. Configure the same rules: minimum age 18, exclude USA, OFAC on.
  3. Publish it. Copy the flowId from 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/core and @selfxyz/qrcode.
  • Remove your ConfigStore implementation.
  • Remove your /verify route, 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

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.completed event if you truly need it.)

Rolling out safely

  1. Build the Enterprise integration behind a feature flag (enterprise: false).
  2. Configure a test-environment flow + webhook endpoint.
  3. QA against mock passports.
  4. Move staging to Enterprise.
  5. Cut over prod with a percentage rollout (10% → 50% → 100%).
  6. 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.