Backend API integration (without the npm SDK)
This is the end-to-end recipe for integrating Zyphe from your backend using the HTTP SDK API (https://api.zyphe.com/sdk/...) directly—no Node, browser, or React Native package required.
You will:
- Create a verification request with a secret API key
- Compose a hosted session URL from the response
- Open that URL in a WebView, iframe, or browser redirect
- Receive results via webhook (and optionally fetch images via the Export API)
If you prefer packages, use the Node SDK for the same API. For product tradeoffs, see Hosted UI vs direct API and Choosing an integration method.
SDK API means the HTTP routes under /sdk/... on api.zyphe.com.
SDK packages means @zyphe-sdk/node, @zyphe-sdk/browser, and related npm libraries. You can use the HTTP API without installing any package.
Prerequisites
| Item | Where |
|---|---|
Secret API key (zyphe_sk_…) | API keys |
| Flow ID (UUID) | Dashboard → flow settings |
| Correct hosts | Environment setup |
| Sandbox flag aligned | Sandbox mode |
| Webhook URL on the flow (recommended) | Webhooks |
1. Create a verification request
curl -X POST "https://api.zyphe.com/sdk/flow/${ZYPHE_FLOW_ID}/vr/create?sandbox=true" \
-H "x-api-key: ${ZYPHE_SECRET_API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"email": "applicant@example.com",
"customData": {
"externalUserId": "user_123",
"plan": "pro"
}
}'
| Piece | Value |
|---|---|
| Method / path | POST /sdk/flow/{flow_id}/vr/create |
| Query | sandbox=true for sandbox, sandbox=false for production (required) |
| Header | x-api-key: zyphe_sk_… (secret key) |
| Body | Identity + optional customData (see below) |
Provide at least one identity: email, and/or credentials such as external ID or wallet (see OpenAPI SdkCreateVerificationRequestPayload).
Response fields you need
A successful response includes (among other fields):
| Field | Use |
|---|---|
verificationRequest.id | Session id → query param zypheVr |
zypheToken | Session JWT → query param zypheToken |
zypheAccessSig | Short-lived access signature → query param zypheAccessSig |
flowSlug | Hosted UI path segment |
flowStepSlug | First incomplete step (informational; URL uses flowSlug) |
isSandbox | Must match the sandbox query you sent |
email | Echo of identity email when present → optional zypheEmail |
Full schema: OpenAPI SdkCreateVerificationRequestResponse.
customData
- Optional JSON object of arbitrary key/value metadata attached to the verification request.
- Round-trips into webhooks as
data.<type>.customDataand top-levelcustom(see Custom fields). - Use opaque business identifiers (your user id, application id). Avoid putting secrets or unnecessary PII in query strings if you also pass metadata on public links.
2. Compose the session URL
https://verify.zyphe.com{/sandbox}/flow/<flowSlug>?zypheVr=<verificationRequest.id>&zypheToken=<zypheToken>&zypheAccessSig=<zypheAccessSig>&zypheEmail=<email>
| Mode | Base path |
|---|---|
Sandbox (sandbox=true) | https://verify.zyphe.com/sandbox/flow/<flowSlug> |
Production (sandbox=false) | https://verify.zyphe.com/flow/<flowSlug> |
Example (sandbox):
https://verify.zyphe.com/sandbox/flow/my-kyc-flow?zypheVr=cf52e18e-28d1-4a2f-8304-c04ef5a75d0f&zypheToken=eyJ...&zypheAccessSig=...&zypheEmail=applicant%40example.com
Optional query parameters supported by the hosted UI and npm helpers:
| Param | Purpose |
|---|---|
zypheFullscreen=true | Fullscreen layout (recommended in mobile WebViews) |
zypheHandoffBaseUrl | Return / handoff base URL for your app |
| Theme params | See Theming |
Always URL-encode query values.
Do not open https://api.zyphe.com/... in a WebView. Users complete verification on verify.zyphe.com. The API host is only for your backend.
3. Present the URL to the user
| Platform | Pattern |
|---|---|
| Web | Redirect the browser, or embed in an iframe (Browser SDK automates this) |
| Mobile | Load the URL in a WebView with camera permissions (Mobile integration) |
| Email / SMS | Send the composed URL (or use a public flow link when you do not need server-side session creation) |
4. Receive results
- Configure a webhook URL on the flow.
- Verify
X-Signature(Webhook signature). - Branch on
event/flowStatus(Statuses and codes). - Correlate with your system via
custom/customData.
Document images are not included in webhook payloads by default. Extended webhooks may include a limited selfie URL; full document media requires the Export API (must be enabled by Zyphe).
5. Optional: complete steps without the hosted UI
You can drive document selection, document upload, and liveness from your backend using the step endpoints documented in OpenAPI and the Node complete-step helpers. That path has important tradeoffs (capture quality, device signals, liveness modes). Read Hosted UI vs direct API before choosing it.
Minimal Node example (raw fetch)
const API = process.env.ZYPHE_API_BASE_URL ?? 'https://api.zyphe.com'
const VERIFY = process.env.ZYPHE_VERIFY_BASE_URL ?? 'https://verify.zyphe.com'
const apiKey = process.env.ZYPHE_SECRET_API_KEY!
const flowId = process.env.ZYPHE_FLOW_ID!
const sandbox = process.env.ZYPHE_SANDBOX !== 'false'
async function createSessionUrl(email: string, customData?: Record<string, unknown>) {
const res = await fetch(`${API}/sdk/flow/${flowId}/vr/create?sandbox=${sandbox}`, {
method: 'POST',
headers: {
'x-api-key': apiKey,
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, customData }),
})
if (!res.ok) {
const err = await res.json().catch(() => ({}))
throw new Error(`Create VR failed: ${res.status} ${JSON.stringify(err)}`)
}
const data = await res.json()
const pathPrefix = data.isSandbox ? '/sandbox' : ''
const params = new URLSearchParams({
zypheVr: data.verificationRequest.id,
zypheToken: data.zypheToken,
zypheAccessSig: data.zypheAccessSig,
})
if (data.email || email) {
params.set('zypheEmail', data.email ?? email)
}
params.set('zypheFullscreen', 'true')
return `${VERIFY}${pathPrefix}/flow/${data.flowSlug}?${params.toString()}`
}
Common failures
| Symptom | Likely cause | Fix |
|---|---|---|
| Connection / HTML error page | API base URL is docs.zyphe.com or another non-API host | Use https://api.zyphe.com |
401 · invalid_api_key | Publishable key, typo, or wrong environment | Use zyphe_sk_…; see API errors |
| Flow / VR not found | sandbox flag does not match the flow | Align flag, dashboard mode, and URL path |
| User stuck / blank WebView | Missing camera permissions or wrong WebView flags | Mobile integration |
| No images in webhook | Expected by design | Export API |