Log in
Start here

KYB developer guide

Early access. Security controls are in place. Tool names, input fields, and documentation may change as we incorporate feedback.

This guide shows the shortest working path for business verification: connect an MCP client, find the correct business, verify it, and retrieve the report. Start with sandbox data. Move to live verification only after the flow works end to end.

Before you start

  • An MCP client that supports streamable HTTP.
  • A business name and country, or a known registration number.
  • Start in sandbox so you can test the full flow without billing.

The flow

  1. Connect. Add https://mcp.trulioo.com/mcp to your MCP client and complete OAuth.
  2. Find the business. Search by name, or look up the registration rules for the country.
  3. Confirm the candidate. If search returns more than one business, ask the user to choose before you verify.
  4. Verify. Call kyb_verify with the selected registration identifier.
  5. Handle the result. Follow next_action when the result is not terminal. Save the transaction ID.
  6. Retrieve the report. Call kyb_get_report after verification completes.

Tools used in this guide

Search for a businesskyb_search · Tools →
Look up registration detailskyb_registration_lookup · Tools →
Verify a businesskyb_verify · Tools →
Retrieve a completed reportkyb_get_report · Tools →
Build with Trulioo

Zero to verified

Early access. Security controls are in place. Tool names, input fields, and documentation may change as we incorporate feedback.

One MCP connection gives any agent KYC, KYB, account analytics, and Know Your Agent - the signed identity an agent carries so anyone can prove who is behind it. There is no key to copy-paste - your client enrols itself over OAuth. Here is the whole path.

  1. Connect the MCP server. Point any MCP client at the hosted endpoint - it discovers the authorization server and registers itself, so there is no key to copy-paste. Client setup →
  2. Call a verification tool. Run kyc_verify or kyb_verify against synthetic test entities and branch on the typed result. Tools →
  3. Give your agent an identity. Verify the organization behind the agent, then mint a signed, scoped attestation with kya_issue_mandate. Know Your Agent →
  4. Let anyone verify it. Publish the attestation in your A2A card; any party checks it against the issuer JWKS - no key needed. Verify agents →

I want to…

Verify a personkyc_verify · Tools →
Verify a businesskyb_verify · Tools →
View business transaction trendsanalytics_query - business profile - Analytics →
Review recent business transactionsanalytics_list_transactions - business profile - Analytics →
See what account analytics can answeranalytics_account_overview - business profile - Analytics →
Screen a name on its ownaml_screen - per-account · Tools →
Capture a document or a selfiedocv_create_session - per-account · Tools →
Prove who is behind an agentKnow Your Agent →
Verify another agent's profile (DAP)kya_verify_agent · Verify agents →
Connect an MCP clientClient setup →
Authenticate with OAuthAuthentication →
Have an agent set this up for meLet your agent introduce you →
Read the docs as an agentindex.md · llms.txt

Let your agent guide your KYB setup

Paste this into your coding agent. It will check the current connection before asking you to configure anything, then guide one sandbox business verification from discovery through report retrieval.

Paste this to your agent

Help me connect Trulioo MCP and complete a KYB verification in sandbox. Read https://mcp.trulioo.com/agent-guide.md first. Check whether Trulioo is already connected, then guide me through business discovery, verification, polling, and report retrieval. Stay within the KYB tools documented in the guide.

agent-guide.md is a focused operating guide for this early access workflow. It covers connection checks, OAuth, business search, optional candidate confirmation, verification, non-terminal results, and report retrieval.

It checks before it acts. The guide first looks for an existing Trulioo connection and confirms the session mode. It starts verification only after the developer confirms the correct business.

Review the KYB workflow and response fields →

The MCP endpoint

One hosted endpoint, spoken over MCP streamable HTTP. Any MCP-compatible client or agent framework connects to the same URL - one integration for your whole fleet.

Endpoint

# Streamable HTTP MCP transport https://mcp.trulioo.com/mcp

One endpoint, two connection modes. Use the client-managed OAuth consent flow for sandbox testing. For a live integration, exchange your Trulioo client_id and client_secret for an MCP access token before connecting to the same endpoint.

Try synthetic data without signing in

Use https://mcp.trulioo.com/mock/mcp for anonymous protocol testing. In a connection tester, enter that URL and leave Auth Header empty. This endpoint returns synthetic data and has a limited feature set. Call trulioo_health, confirm mode: sandbox, then read trulioo_capabilities before choosing a workflow.

claude mcp add --transport http trulioo-sandbox https://mcp.trulioo.com/mock/mcp codex mcp add trulioo-sandbox --url https://mcp.trulioo.com/mock/mcp

/mcp remains the authenticated endpoint for installed plugins. Choose Sandbox during OAuth to evaluate it without Trulioo API credentials. The host root is a documentation page, not an MCP transport. The existing /sandbox/mcp alias still requires OAuth and does not bypass authentication or select a mode.

Connection troubleshooting

ResultNext step
401 on /mcpComplete OAuth or renew the MCP access token. No Trulioo API credentials are required for OAuth Sandbox. For anonymous testing, use /mock/mcp with an empty Auth Header.
HTML or a redirect instead of MCPUse the full transport URL ending in /mcp or /mock/mcp, not the host root.
Callback registration rejectedUse HTTPS or a loopback HTTP callback. Clients with private URI schemes, including Cursor, need the local bridge shown in Client setup.
A tool is missingRead trulioo_capabilities and discover its family with trulioo_find_tools. Availability depends on the connection and enabled features.
Protocol error after connectingLet an MCP SDK manage protocol negotiation and session headers. Raw HTTP clients must follow the negotiated revision; responses may be Server-Sent Events.
Rate limitedHonor the returned retry guidance and use bounded retries. Contact Trulioo before increasing production traffic.

Keep bearer tokens and Trulioo API secrets out of prompts, screenshots, logs, and committed configuration. An MCP access token is distinct from your Trulioo API client secret; use the approved bootstrap below for autonomous live integrations.

For hosted actions that require review, tool approval in the client alone is insufficient. The server requires an actor-bound session and the reviewed Trust Workspace flow. Mock and shared sandbox credentials cannot authorize those actions.

Authentication

/mcp requires an access token. Start with the sandbox connection to validate your KYB workflow. When your account is approved for live use, bootstrap a live token with your Trulioo client credentials.

Sandbox connection

Claude Code, Cursor, Codex, and ChatGPT connect through OAuth 2.1 + PKCE. Clients with private URI callbacks, including Cursor, need a local bridge with a supported callback. OAuth-capable clients manage the flow:

  1. Add https://mcp.trulioo.com/mcp to the client.
  2. The client discovers Trulioo authorization and opens the consent flow.
  3. Choose sandbox.
  4. The client initializes the MCP session and loads the tools available to that connection.

Let the client manage sandbox OAuth. Do not copy sandbox tokens, register a client by hand, or hardcode authorization endpoints.

Start in sandbox

Sandbox uses the same endpoint and tool schemas as live access. It is unbilled and intended for testing the full integration before you work with production data. Sandbox results include a test_mode marker so your application can identify them.

Live integration with client credentials

For an approved live account, store the Trulioo client_id and client_secret in your secret manager or environment. Send them only to the token bootstrap endpoint over TLS.

Request an MCP access token

export TRULIOO_CLIENT_ID="your-client-id" export TRULIOO_CLIENT_SECRET="your-client-secret" # -u sends Authorization: Basic base64(client_id:client_secret) curl -sS -X POST https://mcp.trulioo.com/oauth/token \ -u "$TRULIOO_CLIENT_ID:$TRULIOO_CLIENT_SECRET" \ -H 'content-type: application/x-www-form-urlencoded' \ -d 'grant_type=client_credentials'

Response

{ "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600 }

The bootstrap validates the credentials with Trulioo, holds the upstream credential server-side, and returns a short-lived MCP access token. Store the returned access_token in TOKEN; the Raw JSON-RPC client setup below shows the complete initialization sequence.

export TOKEN="eyJ..."
  • Never send client_secret to /mcp, place it in a URL, or log it.
  • The bootstrap does not return a refresh token. Re-run the bootstrap when the MCP access token expires or the server returns 401.
  • 401 invalid_client means the credentials were malformed or rejected. Retry only after checking the credential configuration.
  • If Trulioo authentication is temporarily unavailable, retry the bootstrap with bounded backoff.

Usage limits

Usage limits apply and may change during early access. If a result includes retry_after_seconds, wait for that interval before retrying. Contact Trulioo before a production-scale rollout so limits can be reviewed for your use case.

Client setup

Pick your client and point it at the hosted endpoint. Use its OAuth flow for sandbox. For live use, the client must support sending the bearer token returned by the client-credentials bootstrap.

Add the endpoint

claude mcp add --transport http trulioo https://mcp.trulioo.com/mcp

After adding the server, open Claude Code, run /mcp, and authenticate Trulioo. Choose Sandbox in the browser, then call trulioo_health to confirm the mode. For a project-scoped server, approve the project's MCP configuration when prompted.

OpenAI Responses API

Include this entry in your request's tools array to try synthetic sandbox without a Trulioo token:

{ "type": "mcp", "server_label": "trulioo", "server_url": "https://mcp.trulioo.com/mock/mcp", "allowed_tools": ["trulioo_health"], "require_approval": "always" }

The API does not run an interactive OAuth login. For the protected /mcp endpoint, obtain a token through Authentication and provide it in the tool's authorization field on every request. Handle MCP approval requests in your application. OpenAI API authentication and billing are separate from Trulioo's synthetic sandbox.

Account analytics

Three read tools answer questions about the authenticated customer's own KYB activity: analytics_account_overview (packages, a 90-day headline, and the state of the account copy), analytics_query (aggregate transaction volume for trends, charts, dashboards, and reports), and analytics_list_transactions (individual transactions, newest first). Account scope is derived server-side from the Trulioo credential. No tool accepts an account id, SQL, a relation name, or an arbitrary filter.

analytics_query supports transaction_volume; day, week (ISO, starting Monday), or month grain; a window of at most 90 days that starts no earlier than 90 days before today (UTC); optional grouping by country, data_source, or product; and a result limit from 1 to 100 (default 100). Grain defaults to day for windows up to 31 days and to week beyond that, and every period is the ISO date its bucket starts. summary.total covers the full requested range even when the bounded series is truncated; the summary reports available and returned series-row counts plus series_truncated.

analytics_list_transactions defaults to the last 7 days and 25 rows per page (limit 1 to 100). Filter by country, data_source, product, or transaction_id, and pass page.next_cursor back as cursor, with the same filters, to continue.

First use. Where the account store is configured, the first analytics call registers a 90-day copy of the account's transactions. Until the requested window is copied a result reports status: "preparing" with sync.progress and a first_use notice, and summary, chart, and the overview headline are null. A copy unused for 30 days is deleted; the next call rebuilds it and says so with a rebuilding_after_eviction notice.

Example: query the authenticated account

curl -sN https://mcp.trulioo.com/mcp \ -H "Authorization: Bearer $TOKEN" -H "mcp-session-id: $SID" \ -H 'MCP-Protocol-Version: 2025-06-18' \ -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":3,"method":"tools/call", "params":{"name":"trulioo_invoke_tool","arguments":{"name":"analytics_query", "arguments":{"metric":"transaction_volume","days":30,"grain":"week", "group_by":"country","limit":100}}}}'

Availability. Analytics is published on the business MCP profile. Sandbox sessions return deterministic synthetic results, ready immediately, for evaluation; test sessions are refused; live sessions need a deployment with an analytics source. On progressive discovery the analytics tools are deferred rather than resident: find them with trulioo_find_tools using family: "analytics", inspect them with trulioo_tool_schema, then call them through trulioo_invoke_tool. If discovery does not return a tool, the connected account or deployment does not expose it.

Going live does not change the MCP URL. It changes how the bearer token is obtained: use the approved account's client_id and client_secret at /oauth/token. Authentication →

KYB tools reference

Tools reference

The KYB surface is a typed sequence: discover the business, resolve ambiguity, verify it, poll when needed, and fetch the report. tools/list remains the authority for the tools available to your account.

Every capability is a typed, discoverable MCP tool - schema-enforced inputs, structured results agents branch on, and no raw passthrough - a tool that is not on your connection is not reachable by another route. A default progressive connection exposes 57 addressable entries: 18 resident tools and 39 deferred product capabilities. The product contract is 55 tools because two resident entries are progressive-only routing tools. Per-account families change the enabled set. The exact resident set is what tools/list returns for your connection, so discover it rather than hardcoding this list.

Example: call a tool over JSON-RPC

curl -sN https://mcp.trulioo.com/mcp \ -H "Authorization: Bearer $TOKEN" -H "mcp-session-id: $SID" \ -H 'MCP-Protocol-Version: 2025-06-18' \ -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call", "params":{"name":"kyb_verify","arguments":{"country_code":"GB","registration_id":"08123456"}}}'
curl -sN https://mcp.trulioo.com/mcp \ -H "Authorization: Bearer $TOKEN" -H "mcp-session-id: $SID" \ -H 'MCP-Protocol-Version: 2025-06-18' \ -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call", "params":{"name":"kyc_verify","arguments":{"country_code":"US","data_fields":{}}}}'

Both headers are required: $TOKEN from Authentication, and $SID from the initialize handshake - see Raw JSON-RPC under Client setup.

KYB workflow and responses

Identity & business verification

StepToolUse it whenResponse and next step
1 kyb_search You have a business name but not a confirmed registration identifier. Returns: search_summary with candidate_count, decision, and selection. Confirm a candidate before verification, then verify it with selection.ref plus its candidate_id; do not use the top-level RecordStatus to decide whether matches were found.
As needed kyb_registration_lookup You need the registration types or jurisdiction details accepted for a country. Returns: supported registration-number types or jurisdictions of incorporation. Use them to format the search or verification input.
As needed (no extra call) Search returns multiple businesses and the user must choose the correct one. Returns: the choice is in the search result. search_summary.selection lists every candidate once with an id, selection.discriminators names the fields that actually separate them, and search_summary.clarification carries a ready-made closed question. Verify with selection.ref plus the chosen candidate_id.
2 kyb_verify You have confirmed the business and are ready to start verification. Returns: transaction_id, record_id, status, is_terminal, and next_action. Branch on status; follow next_action when the result is not terminal.
While running kyb_get_partial_result The verification is still running and you need the latest available state. Returns: the latest available verification fields plus is_terminal and next_action. Continue polling only while the result is not terminal.
3 kyb_get_report The verification is complete and you need the final report. Returns: a structured report, or a PDF descriptor with record_id, report_available, content_type, and resource_uri. Store the report reference with the transaction.
Reference transaction_lookup You need to retrieve a previous verification from its transaction identifier. Returns: the matching record and identity context for a TransactionID or TransactionRecordID. Use the resolved record for status or report retrieval.
ToolDoes
kyc_verifyVerify a person across 195+ countries; returns match / review / nomatch + next-action hints.
kyc_get_status / kyc_get_recordPoll an async verification, then fetch the completed record.
kyb_verifyVerify a business, with UBO discovery and due-diligence sequencing.
kyb_search / kyb_get_reportFind a business, then retrieve its full report.
kyb_registration_lookupRegistration numbers + jurisdictions of incorporation (routes by the args you pass).
kyb_get_partial_resultFetch partial results for a long-running KYB job.
transaction_lookupLook up a past KYC/KYB verification by the transactionId you already hold - resolves a TransactionID or TransactionRecordID to the record + identity.

Per-account families

Off unless your account is entitled to them, each enabled on its own. They are real and supported; they are simply absent from tools/list until your deployment has them. Ask Trulioo for the families you need rather than coding around them, and read the result from tools/list - getting one family does not get you the rest.

ToolDoes
aml_screenStandalone sanctions and PEP screening for a name you are not verifying.
docv_create_sessionStart a document + liveness capture session. Returns a session_url the person opens; images and biometric data never cross the MCP stream.
docv_get_resultRead the outcome of a capture session. Returns a Task to a tasks-capable client; otherwise poll.
docv_cancel_sessionCancel a capture session the person abandoned.
docv_create_mobile_handoffHand a desktop session off to the person's phone for the camera step.
age_checkAge assurance from a known date of birth. Its sibling age_estimate_biometric is declared but returns NotImplemented until biometric estimation ships - do not build against it.
monitoring_enrollPut a verified subject under ongoing monitoring.
monitoring_get_alertRead an alert monitoring raised.
monitoring_refreshRe-run the checks behind an enrollment now.
monitoring_cancelEnd an enrollment.
monitoring_get_enrollmentRead an enrollment's current state.

tools/list and config_discover_account are the authority on what your connection has. Do not hardcode the list above, and do not synthesize a tool name that is not on it - there is no raw passthrough, so a tool that is absent is not reachable by another route.

Know Your Agent

ToolDoes
kya_admission_challengeMint a short-lived, single-use enterprise admission challenge for one privileged target tool. The returned token is bound to the authenticated tenant, session, target tool, and policy version.
kya_possession_challengeMint the single-use nonce a keyed card's possession proof must carry. Call this first - kya_issue_mandate rejects a proof without a fresh nonce. On a software key this proof is also what earns AAL2; tier alone does not.
kya_issue_mandateOne call: verify the organization → register the agent → sign a scoped attestation → anchor it. Returns the attestation JWS + the A2A extension block.
kya_verify_agentVerify another agent's card; optionally check a requested_action against its signed scope (the scoped handshake).
kya_lookupPublic lookup of an agent's standing by DAP handle or fingerprint. depth selects the tier: lookup (free, is it verified and who is it) or verify (paid, adds advisory signals).
kya_list_agentsList a bounded, tenant-scoped page of the authenticated account's agents for selection and Digital Agent Profile inspection. Internal account joins, keys, and recovery authority are excluded.
kya_get_insightsRead complete account agent-inventory counts by status, lifecycle and issuance environment. Retrieval time is supplied; snapshot freshness is unknown. Historical activity, verification rates, plugin release health and runtime assurance are unavailable.
kya_get_agent_metricsRead recorded lifetime lookup counts, a 30-day UTC daily series and a bounded recent feed for one current agent owned by the authenticated standalone connector's account. The source event read limit is 500; all agent interactions and billing usage are unavailable. Shared hosted reads remain unavailable until caller-to-account binding is validated.
kya_get_agent_domainRead the account-bound domain and current proof state for one selected Digital Agent Profile.
kya_start_agent_domain_challengeCreate the exact DNS challenge required to bind the selected agent's domain. The account and agent authority are derived from the connector and opaque Agent-ID.
kya_verify_agent_domainCheck the DNS challenge and mark the selected agent domain verified when the expected proof is present.
kya_card_fingerprintCompute a card's fingerprint before you register it - answers “will this build keep my Digital Agent Profile?”. Costs nothing and spends no issuance - pure arithmetic over the card you supply - but it needs your account key like the rest of the keyed surface: it is a build-time developer utility, not a relying-party read. It names which fields are identity-bearing (name, the first interface URL, code_digest, and the agent_key thumbprint - so rotating your key re-mints too) and which are free to change. Returns no trust verdict.
kya_verify_web_bot_authVerify a Web Bot Auth (RFC 9421) signed HTTP request and resolve it to the agent behind it. Note a bare, replayable signature is AAL1 even at tier 2.
kya_verify_protocolVerify a rail-specific envelope (UCP / AP2 / ACP / x402). A2A cards use kya_verify_agent.
kya_supersede_agentRotate an agent's key or reissue its profile, superseding the prior credential so verifiers follow the replacement.
kya_retire_agentRevoke standing for a retired or compromised agent. A verifier resolving its lookup sees the credential is no longer good.
kya_verify_mandateVerify a mandate credential a counterparty presented to you - signature, issuer, validity window, and with freshness: central_fresh its revocation status. Reach for this rather than kya_get_mandate whenever somebody hands you a credential: reading a mandate by an id lifted out of an unverified document trusts the document to describe itself. Pass amount to also learn whether the sum you are about to authorize sits inside the ceiling the credential declares - advisory only, and it never changes valid. An amount_advisory.within of null means unanswerable, never a pass.
kya_get_mandateRead a mandate you issued: status, validity window, and the signed scope - allowed actions, merchants, and the spend cap. A max_amount of null means uncapped, never a cap of zero.
kya_record_spendRecord a settled spend against a mandate, which is what makes a day/total ceiling answerable at all. Your settlement_id is the de-duplication key: replaying it with the same amount returns recorded: false and counts once, while the same id with a different amount is refused 409 rather than silently overwritten. Recording is not enforcement - it moves no money and blocks nothing.
kya_mandate_spendRead a mandate's spend ledger: the running totals per currency, the declared ceiling, and the headroom left. A remaining of null is not zero - it means there is no headroom to speak of, either uncapped or a per-transaction cap, which limits each purchase rather than depleting.
kya_revoke_mandateRevoke one mandate, with a reason recorded for the audit trail. The capability rails fail closed on the next verify; the A2A discovery tier is OfflineOk by design, so it lags until the credential expires.
kya_revocationsList the mandates already revoked, with the status-list index each one occupies - the bulk read behind a verifier's own cache.
kya_transparency_sthFetch the signed tree head: tree size, root hash, and the issuer's signature over both. The anchor every inclusion proof hangs from. Public - no account needed.
kya_inclusion_proofProve a leaf sits under a signed root (RFC 6962). Public - no account needed. Verify the returned audit path with verify_inclusion_hashed, not verify_inclusion: the served leaf_hash is already hashed, and hashing it twice reports a sound log as broken.
kya_status_listFetch the signed status list as its compact JWS (application/statuslist+jwt) - the revocation bitstring a verifier checks offline. Public. Re-signed per request with a fresh validFrom, so do not cache or diff it by byte hash.
kya_railsWhat each rail demands before you build for it: expected_typ, tier, freshness, binding, signing alg, schema URL, and the issuer JWKS to resolve keys from. Public.
kya_assess_readinessMeasure the public agent-facing documents a host publishes and return evidence-backed reason codes and residuals. It reports no score or grade and requires account credentials.
kya_verify_clientVerify a Client ID Metadata Document before admitting an OAuth client: fetch the https URL that is its client_id under MCP 2026-07-28, validate it against draft-ietf-oauth-client-id-metadata-document-00, and get back the document's origin, its redirect_uris, whether it publishes a key (jwks_uri + private_key_jwt) or is a public client, and any KYA operator claim it carries. Runs the same SSRF-hardened fetch the authorization server runs, so the verdict predicts admission. Two tier fields, deliberately: record_trust_tier is a statement about the URL, request_trust_tier_ceiling is the most a request carrying that client_id could reach - binding the first to a request is the mistake this shape exists to prevent. The carried attestation is never verified here (attestation_verified is always false); the issuer is the source of truth, so follow up with kya_lookup on the fingerprint.
kya_list_artifact_candidatesList a bounded page of this account's unpublished Agentic Releases so a host can present an opaque selection UI without accepting an account id from the caller.
kya_list_publisher_bindingsList this account's publisher namespace bindings and whether each remains active and publishable before release registration.
kya_register_artifactRegister a complete Plugin package as an immutable Agentic Release candidate. The server verifies publisher binding and computes package and distribution digests without publishing it.
kya_publish_artifactPublish a registered Agentic Release candidate using an audited, optimistic-concurrency transition.
kya_revoke_artifactPermanently revoke a compromised Agentic Release. This audited transition is destructive and irreversible.

Discovery, meta & workflow prompts

ToolDoes
trulioo_tool_schemaRead a tool's full input schema and complete authored guidance (up to 8 at a time). The tool list carries a one-line description to keep a client's cold start small; this is where the operational detail lives - required fields per country, which flag actually starts an ownership walk, which result fields are advisory rather than evidence.
trulioo_find_tools / trulioo_invoke_toolProgressive discovery, advertised only when TRULIOO_TOOL_DISCOVERY=progressive. The server then lists an 18-tool resident core (~2.8k tokens instead of ~8.0k) and keeps 29 product capabilities reachable: trulioo_find_tools searches the manifest by keyword or family, trulioo_invoke_tool calls a tool that is not listed. Dispatch passes the same profile, family, rate-limit, circuit-breaker and KYA gates as a direct call, cannot widen a profile or re-enable a disabled family, and refuses destructive verbs - those stay advertised so your client always sees their approval hints.

Sandbox scenarios (sandbox credentials only)

Seed the outcome you want to test before you call a verify tool, instead of hunting for a fixture that happens to produce it. A scenario is a small JSON body you post once and then reference by id; it steers the simulated rail only, so these tools refuse on any connection whose data axis is not synthetic - a seeded outcome must never stand in for a real verification.

ToolDoes
sandbox_seed_scenarioRegister one scenario and get back its scenario_id (scn_ prefix). Idempotent by content: the same body returns the same id, and any change to a steering field returns a new one. Bodies are capped at 16 KiB, 50 scenarios per caller, and expire 15 minutes after they are seeded.
sandbox_list_scenariosList the scenarios this caller has seeded and still holds, with the published caps so an automation suite can size itself rather than discover a limit by failing.
sandbox_reset_scenariosDrop every scenario this caller seeded and report how many went. Scoped to the caller, so one test run cannot clear another's state - call it between suites to start from a known-empty plane.

config_discover_account, config_describe_context, and config_list_test_entities tell an agent what its account can do and which safe test subjects it can use before it starts a KYB flow. trulioo_health and webhook_journal cover liveness and async callbacks. The kyb_due_diligence_workflow prompt sequences search, disambiguation, verification, and screening; prompts/list is the authority on the set your connection offers. trulioo_capabilities and trulioo_getting_started let an agent self-orient.

config_discover_account, config_describe_context, and config_list_test_entities tell an agent what its account can do and which safe test subjects it can use before it asks a user for anything. trulioo_health and webhook_journal cover liveness and async callbacks. Guided workflow prompts (kyc_onboarding_workflow, kyb_due_diligence_workflow) sequence the multi-step flows; prompts/list is the authority on the set your connection offers. trulioo_capabilities and trulioo_getting_started let an agent self-orient. There is no raw passthrough: every upstream call goes through a typed tool, so a tool that is not on your connection is not reachable by another route.

Protocol capabilities (negotiated per connection)

The revision is negotiated at initialize: the floor is 2025-06-18 and the newest draft the server supports is 2026-07-28. Features land only for a client that asked for the revision carrying them - everything else degrades to the floor behavior, so read the negotiated value back from trulioo_capabilities rather than assuming one. Two optional extensions a capable client can opt into:

Handle the result

ResultWhat your code should do
is_terminal:falseDo not treat the verification as complete. Follow next_action and poll within a bounded retry budget.
status: matchContinue the approved business onboarding flow and store the transaction ID.
status: reviewPause automation and route the result to a human reviewer.
status: nomatchStop the onboarding path and present the returned next action.
  • Tasks (io.modelcontextprotocol/tasks) - kyb_verify returns a task handle you poll with tasks/get when your client declares the capability; otherwise it returns the same next_action long-poll. Task state is per-instance today, so a not-found tasks/get means fall back to the poll.
  • Tasks (io.modelcontextprotocol/tasks) - the long-running tools (kyc_verify, kyb_verify) return a task handle you poll with tasks/get when your client declares the capability; otherwise they return the same next_action long-poll. Task state is per-instance today, so a not-found tasks/get means fall back to the poll.
  • MCP Apps / SEP-1865 (io.modelcontextprotocol/ui) - render_app_verdict returns a host-rendered ui:// verdict card (sandboxed iframe, text/html;profile=mcp-app) with a text fallback for non-Apps clients. Enabled per account (TRULIOO_ENABLE_MCP_APPS).

Result contracts

Tools return structured results an agent can branch on directly - not prose to parse.

kyb_verify (terminal shape)

{ "transaction_id": "txn_...", "status": "match", // match | review | nomatch "is_terminal": true, // false = poll or fetch partial result "next_action": { "type": "none" } }

kyc_verify (shape)

{ "transaction_id": "txn_...", "record_id": "rec_...", "status": "match", // match | review | nomatch "is_terminal": true, // false = poll kyc_get_status "next_action": { "type": "none" } }
  • Errors are results, not exceptions. A failed upstream comes back as a typed result the agent can reason about, not a thrown error that ends the run.
  • Circuit breaker per upstream. Each verification surface has its own breaker, so one degraded provider does not take down the others.
  • Async is explicit. is_terminal:false tells the agent to poll rather than assume completion. A long-running operation returns a continuation to poll; exhausting an approved poll budget requires review rather than an unbounded loop.
Know Your Agent

Give an agent an identity

Any agent can claim any name. Know Your Agent proves the real organization behind an agent and issues a signed, scoped, revocable credential - the Digital Agent Profile (DAP) - that anyone can verify. It rides in the agent's A2A card, so trust travels with the agent.

  1. Verify the organization. KYC/KYB + sanctions on the accountable owner behind the agent.
  2. Register the agent. The agent presents its own Ed25519 key; that key is the identity anchor. A build fingerprint binds the credential to this exact agent.
  3. Sign a scoped mandate. kya_issue_mandate mints a short-lived, least-privilege attestation for named scopes (e.g. purchase), signed by identity.trulioo.com.
  4. Publish it. The attestation attaches to your A2A card under capabilities.extensions[] (uri https://identity.trulioo.com/a2a/kya/v1) and is anchored in a tamper-evident log.

The KYA extension on an A2A agent card

{ "capabilities": { "extensions": [{ "uri": "https://identity.trulioo.com/a2a/kya/v1", "params": { "attestation": "<compact JWS, alg=EdDSA>", "display": { "verified": true, "verified_as_of": "<ISO 8601>", "allowed_scopes": ["purchase"], "issuer": "https://identity.trulioo.com", "fingerprint": "<sha256 of the agent key + card>" } } }] } }

Scopes are signed, but enforced by the relying party. Trulioo signs and audits the allowed scopes; the party accepting the agent is what actually enforces them. The attestation is a verifiable claim of trust, not an authorization grant on its own.

How anyone verifies it →  ·  Do it in the portal →

Why agent trust has layers

"Verified" is not one thing. A DAP asserts a stack of independent facts, and a relying party checks the layers its risk calls for. Knowing the layers tells you exactly what a profile does - and does not - prove.

  1. Identity anchor. The agent holds its own key. Everything else binds to that key, so the profile is about this agent, not a name it typed.
  2. Integrity & provenance. A build fingerprint binds the credential to the exact code. Change the code and the fingerprint changes - forcing re-attestation.
  3. Authenticity of use. A possession proof shows the party presenting the card actually controls the anchor key - not a copied card.
  4. Origin & accountability. KYC/KYB ties the agent to a real, sanctions-screened organization, and every issuance is anchored in a tamper-evident log.

This matters to your company directly: it is what lets you (or your customers) accept an agent's action with a known, accountable party behind it - and decline or step up when a layer is missing. The full trust model →

Verify an agent (DAP)

Verification is the critical path: a system deciding whether to trust an inbound agent confirms its Digital Agent Profile and attestation before acting. Verify through MCP; the issuer also publishes the two keyless, public primitives so any party can check a profile with no account.

Try it live

Drive the mint-then-verify lifecycle end to end. This simulation runs entirely in your browser - no network calls. Mint on the left; verify the same agent on the right.

1 - Issue a credential

Verify org → register agent → sign mandate → anchor in the log.

  1. The lifecycle trace streams here - one signed step at a time.

2 - Verify an agent

Against the issuer, not the card. The agent from step 1 lands here.

🔒 Run step 1 first - the agent you mint arrives here to verify.

In an agent (recommended)

Call kya_verify_agent with the agent's card - it validates the signature, fingerprint, expiry and sanctions, and returns the Verified-by-Trulioo record. Add a requested_action to check it against the signed scope in the same step. This is the integration path; the KYA verification logic lives behind MCP, not a public write API.

Verify over MCP

curl -sN https://mcp.trulioo.com/mcp \ -H "Authorization: Bearer $TOKEN" -H "mcp-session-id: $SID" \ -H 'MCP-Protocol-Version: 2025-06-18' \ -H 'content-type: application/json' -H 'accept: application/json, text/event-stream' \ -d '{"jsonrpc":"2.0","id":2,"method":"tools/call", "params":{"name":"kya_verify_agent","arguments":{"agent_card":{ }}}}'

$TOKEN comes from Authentication and $SID from the initialize handshake. If you only need to check a profile and not run a verification, the public keyless lookup below needs neither.

Public, keyless lookup (for any verifier)

The issuer publishes two public primitives at https://identity.trulioo.com so a relying party that isn't running an MCP client can still confirm a profile without an account:

  • GET /kya/attestation/{dap} - look up an agent's current standing by its Digital Agent Profile (the "anyone can check" path).
  • GET /.well-known/jwks.json - the issuer's signing keys (rotation-aware) to verify an attestation JWS yourself.
# look up standing by Digital Agent Profile curl -s https://identity.trulioo.com/kya/attestation/<dap> # or fetch the issuer keys and verify the JWS yourself curl -s https://identity.trulioo.com/.well-known/jwks.json

What a verifier checks: the JWS signature against the pinned issuer key by kid (the algorithm is pinned from the resolved key, never read from the token header - blocks alg:none and alg-confusion); the fingerprint against the agent's own key + card; the exp (short-lived, re-attested on change); verified; assurance.trust_tier against your own minimum; and the signed allowed_scopes. Scopes are signed and auditable but enforced by you, the relying party.

There is no signed sanctions boolean. Signing a standing sanctions_clear would assert a check that may not have run, on a payment-adjacent credential. Screening is an optional provenanced claim carried only when it actually ran, and a hit or review suspends the credential's standing through its status_reference. Check standing, not a boolean.

The DAP wire schema (ats-v2)

A Digital Agent Profile is a conformant SD-JWT-VC (typ: dc+sd-jwt) carrying a vct of https://identity.trulioo.com/vct/agent-profile.1. A passport core is inline - a KYB-verified operator and a composite assurance grade - while the identity, mandate, status and behavior objects are referenced and dereferenced independently. This is the exact record the KYA card flips to; the full JSON Schema is ats-v2-dap.schema.json (governed by ADR-P-022).

DAP 2.0 presentation (public-discovery profile)

{ "typ": "dc+sd-jwt", "vct": "https://identity.trulioo.com/vct/agent-profile.1", "iss": "https://identity.trulioo.com", "sub": "agt_01j9z4k7c8m2q5v3x6n8p0w2a4", "dap": "dap_01j9z4k7c8m2q5v3x6n8p0w2a4", // public Digital Agent Profile handle (what you look up) "agent_id": "agt_01j9z4k7c8m2q5v3x6n8p0w2a4", // internal durable resolver key "build_id": "bld_01j9z4k7c8m2q5v3x6n8p0w2a4", // a code change bumps build_id alone, never agent_id "operator": { // inline; not holder-omittable at tier >= 2 "name": "Acme Payments Ltd", "kyb": "verified", "registration_id": "GB-08123456" // selectively disclosable }, "assurance": { "ial": "2", "aal": "2", "fal": "2", "trust_tier": "2" }, "cnf": { "jkt": "kFx7Q2b...9dE" }, // RFC 7800 holder key (possession-bound) "capabilities": ["read", "checkout", "refund"], "status": "status-list#4021", // Bitstring Status List (referenced) "endorsements": ["A2A", "MCP", "UCP", "AP2"] // rails that honor this profile }

Disclosure integrity. assurance (incl. trust_tier) is always inline; operator (at tier ≥ 2) and screening.result (when present) are not holder-omittable - a holder cannot strip a signed sanctions hit or claim tier ≥ 2 while hiding the operator. Only operator.registration_id, screening.watchlists, and (pairwise profile only) agent_id/build_id are selectively disclosable.

Two profiles. Public discovery reveals agent_id/build_id inline (shown above). Pairwise withholds them via SD-JWT selective disclosure and substitutes a per-relying-party sub alias, so a profile isn't linkable across verifiers. The variant is chosen by the agent's exposure mode - never a caller flag - so an agent can't be tricked into over-disclosing.

How the DAP projects onto each rail

One DAP, issued once, is projected into each protocol's native shape - KYA proves who is accountable; the rail carries and authenticates the transaction. The mapping below is what actually travels on each rail and which DAP claim the verifier reads.

RailWhere the DAP travelsWhat the verifier reads
Google A2A
Live
Inline in the Agent Card under capabilities.extensions[], uri identity.trulioo.com/a2a/kya/v1, as a compact JWS in params.attestation. The attestation JWS against the issuer JWKS, then operator + assurance.trust_tier from the verified DAP.
Google AP2
Live
The DAP is the credential - a conformant SD-JWT-VC AP2 already speaks (typ: dc+sd-jwt), presented as the mandate. iss = identity.trulioo.com, the cnf holder-key proof, and the inline operator/assurance core.
Google + Shopify UCP
Live
Referenced from the merchant profile the business publishes with its signing keys. operator.kyb = verified and assurance.trust_tier - is this a real, screened business?
OpenAI + Stripe ACP
Live
Checked out-of-band before the delegated Stripe token is honored, via kya_verify_agent(card). The signed capabilities scope (e.g. checkout) and operator - is this agent allowed to make this purchase?
Visa TAP
Preview
TAP signs the request (RFC 9421, Ed25519) with the agent key; the DAP is resolved from that key. The cnf.jkt thumbprint maps the signing key to a DAP, then operator - the accountable org behind the key.
Mastercard Agent Pay
Preview
The Agentic Token binds to the DAP's durable agent_id + verified operator. agent_id and operator - the tokenized card is bound to a real, verified organization.
Cloudflare Web Bot Auth
Live
Signed edge requests (RFC 9421) carry Signature-Agent; the DAP sits beneath the signing key. cnf key match + operator/assurance - replaces a spoofable User-Agent with a verified org.
Coinbase x402
Live
The wallet signs the on-chain payment; the DAP rides the bridged A2A card alongside it. The DAP attestation - the wallet moves value, the DAP proves the accountable org behind the agent.
Skyfire
Live
Skyfire's identity token references the DAP as its regulated assurance source. assurance.trust_tier (e.g. trulioo:tier-2) - the KYC/KYB depth the token anchors to.

Across every rail the DAP's role is the same - prove the accountable organization and its signed scope; the rail enforces and settles. No proprietary token, no lock-in: it's a conformant SD-JWT-VC anyone can verify against the issuer JWKS.

Drop-in "Verified" badge

Prefer not to build the UI? Embed the same <trulioo-verified> element Trulioo runs on its own surfaces. It runs the live attestation lookup itself, stays hidden until the agent verifies, and opens the full Digital Agent Profile on click - Organization, Issuer, DAP, verified-as-of, sanctions, attestations, scopes, and a link into the transparency log. One framework-agnostic custom element; no build step. It's live in the hero of the sibling Know Your Agent page.

← live badge (resolves the Trulioo demo agent's real profile)

Embed it

<script type="module" src="https://mcp.trulioo.com/web-components/primitives/trulioo-verified.js"></script> <!-- endpoint returns the live attestation JSON; label shows "Verified" text --> <trulioo-verified endpoint="https://mcp.trulioo.com/demo-api?identity=1&mode=identity" label></trulioo-verified>

Orchestration patterns

The tools are typed and composable, so an agent chains them mid-task and branches on each result. The examples below show how to combine the raw tools.

Pattern 1 - Verify a person before a high-risk action

The agent checks identity mid-conversation and branches on the typed status. Ships as /trulioo-mcp:kyc-onboarding.

# agent calls the tool, then branches on the result kyc_verify({ country: "US", fields: {...} }) → status == "match" // proceed - open the account → status == "review" // hand off / step up → status == "nomatch" // decline, explain next_action # async? is_terminal:false -> poll kyc_get_status

KYB due diligence - discover, verify, screen

Pattern 2 - Onboard a business, then screen it

Find the business, confirm the correct candidate, verify it, and branch on the typed result.

kyb_search("Acme Ltd", "GB") → registration_id // choose from search_summary.selection - no second call kyb_verify({ candidate_ref, candidate_id }) → status == "match" // continue onboarding → status == "review" // route to a human reviewer → status == "nomatch" // stop and follow next_action

Pattern 3 - Give the agent its own identity (KYA)

Once the org behind the agent is verified, mint the agent's DAP so every downstream call is attributable.

kya_issue_mandate({ scopes: ["purchase"] }) → attestation JWS + the A2A extension block # now any counterparty verifies it, keyless: kya_verify_agent({ agent_card }) → operator verified - tier 2

Keep the business identity continuous. Carry the selected registration identifier from search into verification, store the returned transaction ID, and use that transaction as the anchor for report retrieval.

Enterprise agent teams. A fleet shares one MCP connection and one identity layer - every agent inherits the same verification tools, and each carries its own DAP, so downstream systems know which agent (and which accountable org) took an action. One integration, governed centrally.

Full tool reference →  ·  Result contracts →

Security & honest limits

  • Schema-enforced inputs. Every tool validates its arguments (additionalProperties: false), so malformed or injected calls are rejected before reaching an upstream.
  • Prompt-injection resistance. Tools act only on their typed arguments; free-text in a document or field is data, never an instruction to the server.
  • Algorithm pinning. Attestation verification pins the algorithm from the resolved key (EdDSA / ES256 only) - alg:none and alg-confusion attacks are rejected.
  • Honest limits. A DAP proves identity, integrity, scope and accountability - it does not authorize a payment or guarantee behavior. Scope enforcement is the relying party's; certified biometric liveness has a defined boundary. We surface dependencies we do not own.
  • Governed surface. The verification agents and skills behind these tools are eval-gated and release-controlled - the same discipline you would apply to a compliance-critical dependency.

FAQ

Should I search before calling kyb_verify?

Search when you do not already have an authoritative registration identifier. If search returns multiple candidates, choose one from search_summary.selection before verification.

What should I do when search returns several businesses?

Do not guess. search_summary.selection lists every candidate once with an id, and search_summary.clarification carries a ready-made closed question when the rows split on one field. Confirm the correct business, then call kyb_verify with selection.ref plus that candidate_id.

How do I continue after KYB completes?

Use the transaction ID to retrieve and store the completed report.

Does an agent need its own key for KYA?

Yes. The agent's own key is the identity anchor; the profile binds to it. Trulioo does not mint the agent's key for it.

Does the attestation authorize a payment?

No. It is a signed, verifiable claim of identity and scope. Whether to accept an action is the relying party's decision; scope is enforced there.

How does someone verify an agent without a key?

The issuer publishes its signing keys at /.well-known/jwks.json; verification is a public signature check against those keys.