Skip to content

Providers and Integrations

Travel Rule providers carry your transfers to counterparties; screening integrations check them. Your company saves each one's credentials for each environment, through these endpoints or in the dashboard (Travel Rule, Providers; and Integrations). Credential values are never returned: an answer says which fields hold a value.

Method Endpoint Scope Description
GET /api/v2/providers providers:read List providers, with your settings
GET /api/v2/providers/:name providers:read Get a provider
PUT /api/v2/providers/:name providers:write Save credentials for the key's environment
PATCH /api/v2/providers/:name providers:write Enable or disable (live key)
POST /api/v2/providers/:name/test providers:write Test the connection
GET /api/v2/integrations integrations:read List integrations, with your settings
GET /api/v2/integrations/:name integrations:read Get an integration
PUT /api/v2/integrations/:name integrations:write Save credentials for the key's environment
PATCH /api/v2/integrations/:name integrations:write Enable or disable (live key)
POST /api/v2/integrations/:name/test integrations:write Test the connection
Kind Names
Providers notabene, codevasp, veriscope, gtr, sygna
Integrations elliptic, trmlabs, complyadvantage, crystal

Any other name is 404 PROVIDER_NOT_FOUND or 404 INTEGRATION_NOT_FOUND. The key's owner's role needs the matching permission: providers:view, providers:create (a first save), providers:update or providers:test, and likewise for integrations. Saving a provider or integration that your company's plan does not include is 403 TENANT_FEATURE_DISABLED.

Terminal window
curl "$COVALENT_URL/api/v2/providers/notabene" \
-H "x-api-key: $COVALENT_API_KEY"
{
"data": {
"name": "notabene",
"displayName": "Notabene",
"protocol": "notabene",
"protocolLabel": "Notabene",
"website": "https://notabene.id",
"docsUrl": "https://devx.notabene.id/docs/welcome",
"description": "Notabene Transact v2 with managed PII encryption and signed webhooks.",
"fields": [
{ "key": "clientSecret", "label": "Client Secret", "type": "password", "required": true }
],
"callbackPaths": [
{ "method": "POST", "path": "/api/system/trp/notabene/live/provider_id", "label": "Provider events" }
],
"configured": true,
"configuredFields": ["apiUrl", "clientId", "clientSecret", "vaspDid", "webhookSecret"],
"enabled": true,
"priority": 1,
"notes": null,
"lastTestedAt": "2026-10-09T11:00:00.000Z",
"lastTestResult": "success",
"lastError": null,
"createdAt": "2026-10-01T09:00:00.000Z",
"updatedAt": "2026-10-09T11:00:00.000Z"
},
"meta": {
"apiVersion": 2,
"timestamp": "2026-10-09T12:00:00.000Z"
}
}
Field Description
fields Every setting it takes: key, label, type (text, password, textarea or select), required, and options, placeholder and help where they apply. A password field holds a secret.
configured, configuredFields Whether credentials are saved for the key's environment, and which fields hold a value. Values are never returned.
enabled One switch for both environments.
callbackPaths Providers only: the paths the provider calls on your company's host, for the key's environment. Register them with the provider. Empty until the provider is first saved.
lastTestedAt, lastTestResult, lastError The last connection test: success or error.
createdAt, updatedAt null until first saved.

An integration's settings have the same fields, with type (blockchain_analytics, sanctions or kyc) instead of protocol, protocolLabel, callbackPaths and priority.

Each callback path names its environment and the provider's ID, so a provider's events reach only the provider and environment they belong to:

Provider Method Path
Notabene POST /api/system/trp/notabene/<environment>/<providerId>
Global Travel Rule POST /api/system/trp/gtr/<environment>/<providerId>
Veriscope POST /api/system/trp/veriscope/<environment>/<providerId>/incoming
Sygna Bridge POST /api/system/trp/sygna/<environment>/<providerId>/<event>, for each of permission-request, address-validation, txid, cancel and cdd
CodeVASP As listed /api/system/trp/codevasp/<environment>/connections/<providerId>/<endpoint>, for each CodeVASP endpoint: GET v1/vasp/health, POST v1/beneficiary/VerifyAddress, POST v1/beneficiary/transfer, POST v1/beneficiary/transfer/txid, POST and PUT v1/vasp/transfer/status, POST and PUT v1/verification/tx

<environment> is test or live. Copy the exact paths from callbackPaths, prefixed with your company's host. These paths are for providers, not for API keys: each provider's requests are checked with that provider's own signatures, credentials or allowed source addresses. Any other path under /api/system/trp is 404 { "error": "Not found", "code": "NOT_FOUND" }.

Terminal window
curl -X PUT "$COVALENT_URL/api/v2/integrations/elliptic" \
-H "x-api-key: $COVALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"credentials": {
"apiKey": "...",
"apiSecret": "..."
},
"notes": "Sandbox account"
}'
Field Required Description
credentials Yes Values by field key, as text. An empty value keeps the saved one, so one secret can change without resending the rest.
notes No Text of at most 2,000 characters; null clears them; absent keeps them.

Credentials are saved for the key's environment only: a test key never changes live credentials. The answer is the settings: 201 the first time a provider or integration is saved, 200 after that.

Status Code When
422 VALIDATION_ERROR The body fails validation, details.issues.
422 UNKNOWN_FIELDS Fields it does not take, listed in details.fields.
422 MISSING_FIELDS Required fields with no value, sent or saved, listed in details.fields.
422 INVALID_FIELDS Sygna Bridge settings that are not valid, listed in details.fields.
Terminal window
curl -X PATCH "$COVALENT_URL/api/v2/providers/notabene" \
-H "x-api-key: $COVALENT_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "enabled": true }'

{ "enabled": true } or { "enabled": false }, nothing else. The switch routes test and live transfers alike, so it takes a live key: a test key is refused with 403 LIVE_KEY_REQUIRED. Credentials must be saved first: 409 NOT_CONFIGURED. The answer is the settings.

POST /api/v2/providers/:name/test and POST /api/v2/integrations/:name/test connect with the key's environment's credentials, store the result, and answer:

{
"data": {
"success": true,
"message": "Connection successful",
"testedAt": "2026-10-09T12:00:00.000Z"
},
"meta": {
"apiVersion": 2,
"timestamp": "2026-10-09T12:00:00.000Z"
}
}

A failed test answers 200 with success: false and an error. An integration's success message is its own. Without saved credentials for the environment, the test is 409 NOT_CONFIGURED.