Managing Flows
A Flow is a named, reusable verification configuration — it defines which fields and documents are required, biometric method, age rules, geo-blocking, and per-country overrides for a verification. Every call to POST /v2/idv/verify (or a Web SDK Link) runs against a specific Flow, identified by its flowId.
Flows are created only in the Merchant Portal — there is no public endpoint to create one. Once a Flow exists, you can read, update, or delete it programmatically using the endpoints below. See Flows & Groups for how Flows relate to Groups.
Authentication
Same as Managing Groups — HTTP Basic Auth with your merchant API key and secret:
Authorization: Basic base64(apiKey:secret)
Base URL
https://api.cycurid.com/v2/public/flows
The Flow object
{
"flowId": "eb9863fd-bd81-47d6-be5f-e40369c9bffc",
"name": "Standard Onboarding",
"defaultFields": { "dob": true, "phone": true, "email": true },
"defaultDocumentTypes": ["PASSPORT", "DRIVERS"],
"countryOverrides": [],
"geoBlockedCountries": [],
"webhookUrl": null,
"minAge": null,
"maxAge": null,
"createdAt": "2026-01-15T18:32:00.000Z",
"updatedAt": "2026-01-15T18:32:00.000Z"
}
As of this writing, defaultFields, defaultDocumentTypes, countryOverrides, and geoBlockedCountries come back JSON-encoded as strings rather than parsed JSON (confirmed against the live API) — e.g. "defaultDocumentTypes": "[\"PASSPORT\",\"DRIVERS\"]" instead of "defaultDocumentTypes": ["PASSPORT","DRIVERS"]. Call JSON.parse() on each of these four fields before using them. This is a known quirk of the current API, not something you're doing wrong — the example above shows the intended shape after parsing.
| Field | Type | Notes |
|---|---|---|
flowId | string (UUID) | Unique identifier, generated when the Flow is created in the portal. |
name | string | 1-100 characters. Unique within your account. |
defaultFields | object (as a JSON string) | Which optional fields /v2/idv/verify requires by default. |
defaultDocumentTypes | string[] (as a JSON string) | Accepted document types, e.g. PASSPORT, DRIVERS, ID_CARD, RESIDENCY_CARD. |
countryOverrides | array (as a JSON string) | Per-country customization of required fields/document types, or a country marked fully restricted for this Flow. |
geoBlockedCountries | array (as a JSON string) | Countries blocked for this Flow specifically, in addition to any account-wide restrictions. |
webhookUrl | string | null | URL notified on verification events for this Flow, if configured. |
minAge / maxAge | number | null | Applicant age bounds (1-120). null disables that bound. |
createdAt / updatedAt | timestamp |
List Flows
GET /v2/public/flows
Returns all Flows belonging to your merchant account, most recently created first.
curl -X GET https://api.cycurid.com/v2/public/flows \
-H "Authorization: Basic $(echo -n 'YOUR_API_KEY:YOUR_SECRET' | base64)"
Get a Flow
GET /v2/public/flows/:flowId
Returns the Flow object, or 404 if it doesn't exist (or doesn't belong to your account).
Update a Flow
PUT /v2/public/flows/:flowId
All fields are optional — only send the fields you want to change. At least one field must be present, or the request is rejected with 400 { "message": "No fields to update" }.
| Field | Type | Notes |
|---|---|---|
name | string | 1-100 characters. Must remain unique within your account. |
defaultFields | object | Replaces the default field requirements. |
defaultDocumentTypes | string[] | Replaces the accepted document types. |
countryOverrides | array | Replaces per-country overrides. |
geoBlockedCountries | array of {countryAlpha2, countryName} | Replaces the Flow-specific blocked country list. |
webhookUrl | string | "" | Must be a valid URL, or an empty string to clear it. Max 500 characters. |
minAge / maxAge | number | null | Whole number, 1-120. null removes the bound. |
Every field you send fully replaces the existing value for that field — there's no merge/patch semantics within a field (e.g. sending defaultDocumentTypes replaces the whole array).
If a Flow (via defaultFields/defaultDocumentTypes, or a country override) requires a document type, it must also specify how that document is captured — documentFileUpload: true or documentCapture: true in the relevant fields object. Omitting both returns:
{ "message": "An upload method is required when a document type is selected" }
This is validated against the Flow's effective post-update configuration, so a partial update that only touches one part can still fail this check based on fields you didn't send.
curl -X PUT https://api.cycurid.com/v2/public/flows/eb9863fd-bd81-47d6-be5f-e40369c9bffc \
-H "Authorization: Basic $(echo -n 'YOUR_API_KEY:YOUR_SECRET' | base64)" \
-H "Content-Type: application/json" \
-d '{ "minAge": 18 }'
Delete a Flow
DELETE /v2/public/flows/:flowId
Permanently deletes the Flow.
curl -X DELETE https://api.cycurid.com/v2/public/flows/eb9863fd-bd81-47d6-be5f-e40369c9bffc \
-H "Authorization: Basic $(echo -n 'YOUR_API_KEY:YOUR_SECRET' | base64)"
Returns 200:
{ "message": "Flow deleted successfully" }
Deleting a Flow that's still referenced by a Group or used as a flowId in ongoing integrations will break those references. There's no dependency check before deletion — confirm nothing depends on the Flow first.
Errors
| Status | Meaning |
|---|---|
400 | Request body/params failed validation, or (on PUT) the body had no updatable fields, or the effective config is missing a document upload method. |
401 | Missing or malformed Authorization header. |
400 | Invalid API key/secret combination. |
403 | Merchant application is not completed or approved. |
404 | Flow not found (wrong flowId, or it belongs to another account). |
409 | A Flow with that name already exists on your account. |
Notes
- There is no
POST(create) endpoint here — create Flows in the Merchant Portal's Configuration page, then manage them programmatically with the endpoints above. - Flow names are unique per merchant account, not globally.
- Your subscription plan may limit the total number of Flows you can create in the portal.