Skip to main content
Emblem Developer Docs
Emblem Connect (Partner Integration)

Enrollment Flow

Create an Emblem pass after your provider verification succeeds.

What Enrollment Is

Enrollment lets a user create an Emblem pass after your provider has already verified them. The user opts in, completes passkey creation on Emblem, and can skip verification next time through assertion.

When To Use It

Use enrollment after:

  • Your own verification flow completed successfully.
  • You have the verification facts you need.
  • The user chooses to create an Emblem pass.

Enrollment is not automatic. It is an explicit post-verification opt-in flow.

Prerequisites

You need:

  • A provisioned client_id
  • A registered redirect_uri
  • A secret API key (emb_sk_...)

The same client_id used for assertion can be used for enrollment, but it must also be provisioned with credential issuance authority.

End-to-End Flow

Your verification completes successfully
User opts in to "Create an Emblem pass"
Your server  →  POST /api/v1/credentials/enroll/start  →  receives enrollment_url
Browser      →  redirects to Emblem                    →  user creates passkey
Browser      →  returns to your redirect_uri           →  with status or error

Start Enrollment

POST /api/v1/credentials/enroll/start records verification provenance and creates the enrollment session in one call.

import crypto from 'node:crypto'
import { createClient } from '@emblemapp/sdk'

const emblem = createClient({
  apiKey: process.env.EMBLEM_SECRET_KEY!,
})

const enrollment = await emblem.startEnrollment({
  client_id: process.env.EMBLEM_ASSERTION_CLIENT_ID!,
  redirect_uri: 'https://provider.example/emblem/enroll/callback',
  state: crypto.randomUUID(),
  provider: 'SAFEPASSAGE',
  verification_level: 'L1',
  external_verification_id: 'provider-verification-123',
  verified_at: new Date().toISOString(),
  external_user_ref: 'user-123',
  external_session_ref: 'journey-456',
})

res.redirect(enrollment.enrollment_url)

Request fields

FieldRequiredDescription
client_idYesYour provisioned authorization client
redirect_uriYesCallback URI to receive the final enrollment outcome
stateYesYour CSRF or correlation value
providerYesVerification provider enum, currently SAFEPASSAGE, PRIVATEAV, or EMBLEM_LEGACY
verification_levelYesVerification level satisfied by your verification: L1 or L2
external_verification_idYesImmutable provider-side verification identifier
verified_atYesISO-8601 timestamp for when your verification completed
external_user_refNoYour user reference
external_session_refNoYour journey or session reference

Response fields

FieldDescription
enrollment_urlRedirect target for the Emblem-hosted passkey flow
correlation_idTrace identifier for support and logs
expires_atSession expiry timestamp. Enrollment sessions last 10 minutes

One call records provenance and starts enrollment

Enrollment start is both the provenance-recording step and the browser-session creation step. There is no separate issuance API call in the Connect flow.

Callback Handling

Enrollment is terminal on the browser callback. There is no back-channel code exchange step.

Success callback

https://provider.example/emblem/enroll/callback?status=success&state=opaque_state

Failure callback

https://provider.example/emblem/enroll/callback?error=cancelled&error_code=USER_CANCELLED&state=opaque_state

Callback outcomes

Query paramsMeaning
status=success, stateThe user completed passkey creation successfully
error, error_code, stateThe flow ended without successful enrollment

Current callback error mappings

errorerror_codeMeaning
expiredSESSION_EXPIREDEnrollment session expired
already_usedSESSION_ALREADY_USEDEnrollment link was already consumed
unavailableCLIENT_UNAVAILABLEClient is unavailable for enrollment
cancelledUSER_CANCELLEDUser cancelled the flow
not_supportedPASSKEY_NOT_SUPPORTEDBrowser or platform does not support passkeys
already_registeredALREADY_REGISTEREDThe passkey already exists
registration_failedREGISTRATION_FAILEDPasskey registration failed
invalid_requestINVALID_REQUESTThe enrollment flow could not continue because the request was invalid

Always validate state on callback before treating the flow as complete.

Idempotency

Enrollment start is idempotent on external_verification_id within the same client_id.

  • If you retry with the same external_verification_id and the same immutable verification details, Emblem reuses the stored provenance and returns a fresh enrollment_url.
  • If you retry with conflicting verification details, Emblem returns 409 IDEMPOTENCY_CONFLICT.

Treat external_verification_id as immutable per completed verification.

Error Reference

Start enrollment errors

CodeHTTP statusMeaningWhat to do
VALIDATION_ERROR400Request body failed validationCheck required fields, enums, and ISO-8601 timestamps
INVALID_REDIRECT_URI400redirect_uri is not registered for the client, or it already contains reserved enrollment callback paramsRegister the exact URI you send and exclude state, status, error, and error_code
UNAUTHORIZED401Missing or invalid secret keyCheck Authorization: Bearer emb_sk_...
PUBLISHER_SUSPENDED403Tenant is suspended by EmblemContact Emblem support or your account owner
CLIENT_INACTIVE403Authorization client is inactiveAsk Emblem to activate the client
ISSUANCE_NOT_ALLOWED403Client is not provisioned for credential issuanceAsk Emblem to enable enrollment authority for the client
NOT_FOUND404Authorization client not foundVerify client_id and environment alignment
RATE_LIMITED429Too many requestsBack off and honor Retry-After
IDEMPOTENCY_CONFLICT409The same external_verification_id was reused with conflicting detailsTreat the verification tuple as immutable
INTERNAL_ERROR500Emblem-side failureRetry if appropriate and log request_id / correlation_id

Notes

  • redirect_uri must be registered on the authorization client.
  • redirect_uri must not already include state, status, error, or error_code query params. Emblem owns those callback keys and will reject ambiguous enrollment callback URIs.
  • Connect endpoints use secret-key server auth only.
  • Enrollment requires separate issuance authority even if the same client is already approved for assertion.

On this page