Skip to content

Connect a payment processor

The processor_connections.create operation: POST /api/v1/processor_connections in the REST API and the processor_connections_create tool in the MCP server.

POST/api/v1/processor_connections

Connects a payment processor account to the legal entity of the request, in the request's mode. Ownrecord tests the key at the processor, stores it encrypted (it is never shown again), and sets up the webhook endpoint the processor sends payment events to.

  • Stripe (processor: "stripe"): a restricted key (rk_live_…; test mode also takes rk_test_… or sk_test_…) with write access to PaymentIntents, SetupIntents, PaymentMethods, Customers, Refunds, Disputes and Webhook Endpoints and read access to Balance and Payouts, plus the account's publishable key (pk_…). A key missing permissions is refused with processor_permissions_missing listing them. Ownrecord creates the webhook endpoint on the account itself; on a development machine (no public URL) pass the signing secret of stripe listen --print-secret as webhookSecret instead and forward events with the Stripe CLI.
  • Mollie (processor: "mollie"): an API key of the request's mode (live_… or test_…, from Mollie's dashboard → Developers → API keys), bound to one website profile; or an organization access token (access_…) with profileId (pfl_…), which reconciliation of Mollie's balance transactions needs (an API key is accepted and reports balances.read as missing). Checkout redirects buyers to Mollie's payment page, which offers the methods enabled on the profile (cards, iDEAL, Bancontact, SEPA Direct Debit for renewals, …). Mollie needs no webhook setup: every payment Ownrecord creates carries this connection's webhook URL.
  • Fake (processor: "fake"): the development and CI processor, only where development access is on. The key is optional.

Brands then use the connection for checkout (spec §15.4; processor_connections.routing.update sets a brand's primary and secondary). Needs a sign-in within the last 15 minutes in the console; security tier for agents.

At a glance

  • REST: POST /api/v1/processor_connections
  • MCP tool: processor_connections_create
  • Operation ID: processor_connections.create
  • Scope: Legal entity
  • Permission: processors:admin
  • Risk tier: security
  • Dry run: Not supported
  • Idempotency: Idempotency-Key required
  • Modes: Test and live
  • Authentication: API key with the processors:admin scope
  • Fresh sign-in: In the console, a sign-in within the last 15 minutes
  • Since: M4

Request

Body

A JSON object (Content-Type: application/json):

FieldTypeRequiredDescription
processorone of stripe, mollie, fakeYes
labelstringNo
apiKeystringNo
publishableKeystringNo
webhookSecretstringNo
profileIdstringNo

Response

201 Created with a JSON object:

FieldTypeDescription
idpcon_… ID
object"processor_connection"
entityIdent_… ID
livemodeboolean
processorone of stripe, mollie, fake
labelstring
statusone of active, degraded, disconnected
statusReasonstring or null
accountIdstring or null
keyHintstring
publishableKeystring or null
checkoutComponentone of stripe_payment_element, redirect, fake
webhookobject
webhook.modeone of managed, manual
webhook.urlstring
webhook.endpointIdstring or null
webhook.lastEventAtdate-time or null
lastTestobject
lastTest.okboolean
lastTest.missingPermissionsarray of string
lastTest.messagestring or null
lastTest.checkedAtdate-time
failuresobject or null
disconnectedAtdate-time or null
createdAtdate-time
updatedAtdate-time
versioninteger (at least 1)

Examples

Connect Stripe in test mode

HTTP
POST /api/v1/processor_connections
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "processor": "stripe",
  "apiKey": "rk_test_ExampleOnlyNotARealKey000000000AbCd",
  "publishableKey": "pk_test_ExampleOnlyNotARealKey000000000AbCd"
}

Response (201):

JSON
{
  "id": "pcon_01m4vyt4mxe0s9zzk90373z6p6",
  "object": "processor_connection",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "livemode": false,
  "processor": "stripe",
  "label": "Stripe",
  "status": "active",
  "statusReason": null,
  "accountId": "acct_1ExampleAccount01",
  "keyHint": "rk_test_…AbCd",
  "publishableKey": "pk_test_ExampleOnlyNotARealKey000000000AbCd",
  "checkoutComponent": "stripe_payment_element",
  "webhook": {
    "mode": "managed",
    "url": "https://ownrecord.io/api/webhooks/stripe/pcon_01m4vyt4mxe0s9zzk90373z6p6",
    "endpointId": "we_1ExampleEndpoint01",
    "lastEventAt": null
  },
  "lastTest": {
    "ok": true,
    "missingPermissions": [],
    "message": null,
    "checkedAt": "2026-10-14T12:00:00.000Z"
  },
  "failures": null,
  "disconnectedAt": null,
  "createdAt": "2026-10-14T12:00:00.000Z",
  "updatedAt": "2026-10-14T12:00:00.000Z",
  "version": 1
}

Connect Mollie in test mode with an API key

HTTP
POST /api/v1/processor_connections
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "processor": "mollie",
  "apiKey": "test_ExampleOnlyNotARealMollieKey0AbCd"
}

Response (201):

JSON
{
  "id": "pcon_01m4vyt4mxe0s9zzk90373z6p9",
  "object": "processor_connection",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "livemode": false,
  "processor": "mollie",
  "label": "Mollie",
  "status": "active",
  "statusReason": null,
  "accountId": "pfl_ExampleProf1",
  "keyHint": "test_…AbCd",
  "publishableKey": null,
  "checkoutComponent": "redirect",
  "webhook": {
    "mode": "managed",
    "url": "https://ownrecord.io/api/webhooks/mollie/pcon_01m4vyt4mxe0s9zzk90373z6p9",
    "endpointId": "mollie_payment_webhooks_0123456789abcdef01234567",
    "lastEventAt": null
  },
  "lastTest": {
    "ok": true,
    "missingPermissions": ["balances.read"],
    "message": "Connected with an API key. Reconciliation of Mollie balance transactions needs an organization access token (access_…) with balances.read.",
    "checkedAt": "2026-10-14T12:00:00.000Z"
  },
  "failures": null,
  "disconnectedAt": null,
  "createdAt": "2026-10-14T12:00:00.000Z",
  "updatedAt": "2026-10-14T12:00:00.000Z",
  "version": 1
}

Use the fake processor in development

HTTP
POST /api/v1/processor_connections
Authorization: Bearer or_test_…
Idempotency-Key: 3f1c9a52-7d0e-4b8f-9a61-0c2d5e8b7f14
Content-Type: application/json

{
  "processor": "fake"
}

Response (201):

JSON
{
  "id": "pcon_01m4vyt4mxe0s9zzk90373z6p7",
  "object": "processor_connection",
  "entityId": "ent_01m4ttwd3veh9apbewxheq5xh4",
  "livemode": false,
  "processor": "fake",
  "label": "Fake processor",
  "status": "active",
  "statusReason": null,
  "accountId": "acct_fake_0123456789abcdef",
  "keyHint": "fake_…9f2c",
  "publishableKey": null,
  "checkoutComponent": "fake",
  "webhook": {
    "mode": "managed",
    "url": "http://localhost:3000/api/webhooks/fake/pcon_01m4vyt4mxe0s9zzk90373z6p7",
    "endpointId": "we_fake_0123456789abcdef01234567",
    "lastEventAt": null
  },
  "lastTest": {
    "ok": true,
    "missingPermissions": [],
    "message": null,
    "checkedAt": "2026-10-14T12:00:00.000Z"
  },
  "failures": null,
  "disconnectedAt": null,
  "createdAt": "2026-10-14T12:00:00.000Z",
  "updatedAt": "2026-10-14T12:00:00.000Z",
  "version": 1
}

Errors

CodeHTTP statusWhenWhat to do
validation_failed400A key is missing or isn't shaped like the processor's keys, or a field doesn't apply to the processor.Fix the fields listed in details.issues and send the request again.
processor_not_available400The fake processor outside development.Connect Stripe or Mollie. The fake processor exists only in development and test.
processor_key_mode_mismatch400A key belongs to the other mode.Use a test key (Stripe rktest…, Mollie test*…) for a test-mode connection and a live key (rk_live*…, live_…) for a live-mode connection, or switch the console's mode.
processor_key_not_restricted400A live connection with the account's secret key (sklive…).Create a restricted key (rklive…) with the permissions listed in the docs instead of using the account's secret key (sklive…).
processor_credentials_invalid400The processor rejected the key.Copy the key again from the processor's dashboard (Stripe: Developers → API keys). It may have been rolled or deleted.
processor_permissions_missing400The restricted key lacks permissions (details.missing_permissions).Edit the restricted key in the processor's dashboard and grant the permissions listed in details.missing_permissions, then try again.
processor_webhook_url_not_public400Stripe can't reach this deployment; pass webhookSecret.On a development machine, run stripe listen --print-secret, pass the secret it prints (whsec_…) as webhookSecret, then forward events with stripe listen --forward-to the connection's webhook URL.
processor_account_already_connected409The account is already connected to the entity in this mode.Rotate the key of the existing connection (processor_connections.update) instead of connecting again.
processor_request_failed502The processor couldn't be reached or refused the request.If retryable is true, retry with the same Idempotency-Key after a short wait; otherwise check details.code.
upstream_timeout502The processor didn't answer in time.Retry the request with the same Idempotency-Key after a short wait.
scope_required400The request names no legal entity.Call the operation with credentials or a target at its level: an organization, a legal entity, a brand or the platform (details.required_scope).
permission_denied403You can't manage processor connections here.Ask an organization owner or admin for a role or scope that allows this action.
fresh_auth_required403Your last sign-in is older than 15 minutes.Sign in again, then repeat the action within 15 minutes.

It can also return these common errors: api_version_unsupported, invalid_json, unsupported_media_type, authentication_required, api_key_invalid, resource_not_found, idempotency_key_required, idempotency_key_reused, idempotency_in_progress, dry_run_not_supported, approval_required, approval_rejected, approval_expired, stale_approval, approval_policy_denied, rate_limited, internal_error.