Vopify MCP Integration
Vopify exposes a Model Context Protocol (MCP) endpoint that allows AI assistants and automation tools to run payee verifications, retrieve verification history, and check account status on behalf of authenticated users. Compatible with Claude, ChatGPT, n8n, and any MCP-compatible tool.
Endpoint: https://vopify.io/mcp
Transport: Streamable HTTP (MCP spec 2025-06-18)
Auth: OAuth 2.1 — Bearer tokenAuthentication
Vopify's MCP uses OAuth 2.1 with bearer tokens issued by Supabase Auth. When connecting a new tool, you will be redirected to log in with your Vopify account credentials. The resulting bearer token is scoped to your account — all verifications consume credits from your balance.
Token issuer: https://<project>.supabase.co/auth/v1
Audience: authenticatedAvailable tools
Vopify exposes 3 tools via MCP. All tools return the standard MCP CallToolResult shape — a content array where content[0].text contains the JSON-stringified payload, and a structuredContent object containing the same data parsed.
typescript{ content: [{ type: "text", text: string }], // JSON-stringified payload structuredContent?: object, // same payload as parsed object isError?: boolean // true on failure }
verify_payee
Runs a real-time Verification of Payee check against the specified payment network and account details. Consumes 1 credit only when a verification result is returned (errorCategory: "verification_complete"). Credits are not charged for input errors or service failures.
| Parameter | Type | Required | Description |
|---|---|---|---|
| network | enum | ✅ Always | Payment network: EUR, GBP, VND, INR, IDR, KRW, CNY |
| name | string | ✅ Always | Account holder name — 1–200 characters |
| holderType | enum | ✅ Except CNY | individual or business — ignored for CNY |
| iban | string | ✅ EUR, optional GBP | Required for EUR. For GBP use either iban or sortCode + accountNumber |
| sortCode | string | GBP only | 6-digit UK sort code — dashes stripped automatically |
| accountNumber | string | GBP (if no iban), INR, IDR, KRW, VND | Bank account number |
| ifscCode | string | INR only | Indian IFSC code e.g. HDFC0001234 |
| bankCode | string | IDR, KRW, VND | Bank identifier code |
| alipayId | string | CNY only | Alipay registered phone number or email address |
Network quick-reference
| Network | network | holderType | iban | sortCode + accountNumber | ifscCode | bankCode | alipayId |
|---|---|---|---|---|---|---|---|
| SEPA / EUR | EUR | ✅ | ✅ | — | — | — | — |
| UK CoP / GBP | GBP | ✅ | IBAN or | sort code + account | — | — | — |
| Vietnam / VND | VND | ✅ | — | ✅ | — | ✅ | — |
| India / INR | INR | ✅ | — | ✅ | ✅ | — | — |
| Indonesia / IDR | IDR | ✅ | — | ✅ | — | ✅ | — |
| South Korea / KRW | KRW | ✅ | — | ✅ | — | ✅ | — |
| China / Alipay | CNY | ❌ | — | — | — | — | ✅ |
Success response — structuredContent
typescript{ errorCategory: "input_validation" | "bank_limitation" | "verification_complete" | "transient_error", verificationOutcome: "match" | "partial_match" | "no_match" | null, errorCode: string | null, resolvedName: string | null, // partial_match only — always null for CNY message: string, // user-facing, safe to display directly creditCharged: boolean, // true only when errorCategory === "verification_complete" creditsRemaining: number, network: "EUR" | "GBP" | "VND" | "INR" | "IDR" | "KRW" | "CNY" }
| Field | Description |
|---|---|
| errorCategory | Classification of the result. verification_complete — result returned, 1 credit charged. input_validation — invalid inputs, no credit charged. bank_limitation — bank doesn't support verification, no credit charged. transient_error — temporary failure, no credit charged. |
| verificationOutcome | The match result. Only populated when errorCategory is verification_complete. |
| resolvedName | The correct name held by the bank. Populated on partial_match only. Always null for CNY. |
| message | User-facing description of the result — safe to display directly in your UI or workflow. |
| creditCharged | true only when errorCategory === "verification_complete". |
| creditsRemaining | Your updated credit balance after this call. |
match or no_match only — partial_match is not supported on this network. resolvedName will always be null for CNY.Example responses
json{ "errorCategory": "verification_complete", "verificationOutcome": "match", "errorCode": null, "resolvedName": null, "message": "The account holder name matches.", "creditCharged": true, "creditsRemaining": 147, "network": "EUR" }
Error responses (isError: true)
"Not authenticated"— no valid session, re-authenticate"Invalid IBAN format"— IBAN failed pre-validation before reaching the server
list_verifications
Returns the authenticated user's recent verification history, most recent first. Results are scoped to the authenticated account — you cannot retrieve another user's history.
| Parameter | Type | Required | Default | Constraints | Description |
|---|---|---|---|---|---|
| limit | integer | ❌ | 20 | 1–100 | Number of recent records to return |
content[0].text contains the JSON-stringified array directly — not wrapped in an object. structuredContent contains { rows: [...] }. Always read from structuredContent in n8n and programmatic clients to avoid double-parsing.typescript{ rows: Array<{ created_at: string, // ISO 8601 timestamp iban_suffix: string, // last 4 digits only — full IBAN never returned provided_name: string, // the name that was submitted result_status: "FULL_MATCH" | "PARTIAL_MATCH" | "NO_MATCH" | "UNAVAILABLE", suggested_name: string | null // populated for PARTIAL_MATCH only }> }
json{ "rows": [ { "created_at": "2025-07-10T14:32:00Z", "iban_suffix": "4300", "provided_name": "Martijn de Vries", "result_status": "FULL_MATCH", "suggested_name": null }, { "created_at": "2025-07-10T13:11:00Z", "iban_suffix": "7890", "provided_name": "Ji-woo Park", "result_status": "PARTIAL_MATCH", "suggested_name": "Ji Woo Park" } ] }
Error responses (isError: true)
"Not authenticated"— no valid session- DB error message — surface to your logging system, do not display to end users
account_status
Returns the authenticated user's credit balance and active plan. Takes no parameters — pass an empty object {}.
Parameters: None.
typescript{ email: string | null, credits: number, plan: string | null }
json{ "email": "operations@vopify.io", "credits": 1348, "plan": "Growth" }
Error responses (isError: true)
"Not authenticated"— no valid session
Connecting Vopify MCP
- In Claude, click the + icon in the message composer
- Select Connectors → search for Vopify
- Click Connect and log in with your Vopify account credentials
- Once connected, Claude can call all three tools on your behalf
- Try: "Verify that IBAN NL91ABNA0417164300 belongs to Martijn de Vries — individual account, SEPA network"
Error handling
When a tool call fails at the transport or auth level, the response will have isError: true and content[0].text will contain a plain text error message. Always check isError before reading structuredContent. For application-level results (invalid inputs, bank limitations etc.) isError will be false — use errorCategory to determine the outcome instead.
javascriptconst result = await mcpClient.callTool("verify_payee", params); if (result.isError) { // Transport or auth failure — re-authenticate or retry console.error(result.content[0].text); return; } const data = result.structuredContent; switch (data.errorCategory) { case "verification_complete": // 1 credit charged — process the result console.log(data.verificationOutcome); // "match" | "partial_match" | "no_match" console.log(data.resolvedName); // suggested name for partial_match break; case "input_validation": // No credit charged — fix the inputs console.log(data.message); break; case "bank_limitation": // No credit charged — bank doesn't support verification console.log(data.message); break; case "transient_error": // No credit charged — retry after a delay break; }
Credits and billing
- 1 credit is consumed per
verify_payeecall whereerrorCategory === "verification_complete" - No credit is charged for
input_validation,bank_limitation, ortransient_erroroutcomes creditCharged: truein the response confirms a credit was consumedcreditsRemainingshows your updated balance after every call- If your balance reaches 0,
verify_payeereturnserrorCategory: "input_validation"with an insufficient credits message — no credit consumed - Check your balance anytime using
account_statusor at vopify.io/billing
Need help?
For integration support, email operations@vopify.io with subject line MCP Integration Support. Include your client platform (n8n, Claude, ChatGPT, or custom), the tool you're calling, the parameters you're sending (redact any real IBANs or account numbers), and the full response you're receiving.