Integrations
Integrate App Connections
OAuth connections to external applications are planned and not available. The connection model they will reuse exists today for billing providers. This page shows how to connect your own Stripe or Paddle account to an environment, register its webhook path, map a plan to a provider price and keep the credential rotated.
Not available yet — App Connections is a planned capability. It is not part of Paycux today and cannot be enabled from the console. What Paycux provides today.
Before you begin
- A member with the owner or admin role. Other roles can read connections but not create or change them.
- A project and an environment. Connections belong to one environment, and development, preview and production never share one.
- Your own Stripe or Paddle account and a key whose prefix matches the mode you choose: test or live for Stripe, sandbox or live for Paddle.
- A catalog plan in the environment to map to a provider price once the connection is active. Hosted checkout sells through that mapping.
Install
There is nothing to install. Paycux is a plain HTTPS JSON API, so every example on this page uses curl. Console routes send the dashboard session cookie, end-user routes send the application's realm access token as a bearer credential, and agent routes send the short-lived agent token. The routes that exist today are listed on What exists today.
1# Console routes carry the dashboard session cookie set by sign-in2curl https://api.paycux.com/v1/auth/session \3 -H "Cookie: __Host-paycux_session=<session>"45# End-user routes carry the application's realm access token6curl https://api.paycux.com/v1/<end-user route> \7 -H "Authorization: Bearer <realm access token>"
Configure
Your application never holds the provider key or talks to the provider directly for checkout. It needs the API address and the scope it calls with; the connection is an operator-side object.
1PAYCUX_API_BASE_URL=https://api.paycux.com2PAYCUX_PROJECT_ID=<project id>3PAYCUX_ENVIRONMENT_ID=<environment id>
Then, in the dashboard:
- 1Open the project, then the environment, then Connections. Create a connection with a name, the provider, the mode and the API key. Add the signing secret now if the provider has shown it.
- 2Copy the webhook path from the new connection and register it with your provider as an endpoint. The connection stays pending until the first event verifies.
- 3Once the connection is active, open Catalog and map a plan to the provider price id. Hosted checkout sells the highest mapped version of a plan key.
- 4Rotate the key or the signing secret from the Connections page when the provider rotates it, Paycux first and then the provider for the signing secret.
Implement
Four console-session calls cover the lifecycle: create, attach or rotate the signing secret, map a plan to a provider price, and list. The webhook endpoint is the one call your provider makes.
Create a connection
The key is verified with a read-only provider call before it is stored; a rejected key stores nothing. The response carries the webhook path to register with the provider and never the key.
1curl -X POST "https://api.paycux.com/v1/environments/<environment id>/provider-connections" \2 --cookie "__Host-paycux_session=<session cookie>" \3 -H "Content-Type: application/json" \4 -d '{5 "projectId": "<project id>",6 "name": "paddle-sandbox",7 "provider": "paddle",8 "mode": "sandbox",9 "apiKey": "<Paddle sandbox API key>",10 "webhookSecret": "<Paddle notification secret>"11 }'1213# 201 Created14{15 "id": "<connection id>",16 "name": "paddle-sandbox",17 "provider": "paddle",18 "mode": "sandbox",19 "status": "pending_webhook_verification",20 "hasWebhookSecret": true,21 "createdAt": "2026-10-13T09:00:00.000Z",22 "updatedAt": "2026-10-13T09:00:00.000Z",23 "webhookPath": "/v1/provider-connections/<connection id>/webhooks/paddle"24}
Register the webhook endpoint with the provider
The provider posts to the connection's own path. Paycux verifies each delivery against the connection's signing secret before it reads the body, encrypts the raw payload before storing it, and treats the first verified event as proof that the endpoint and the secret are right.
1# Endpoint URL to register2https://api.paycux.com/v1/provider-connections/<connection id>/webhooks/paddle34# For a Stripe connection5https://api.paycux.com/v1/provider-connections/<connection id>/webhooks/stripe67# First verified delivery: status pending_webhook_verification -> active
Attach or rotate the signing secret
A connection created without a signing secret receives one through the webhook-secret call. An existing secret is replaced through rotate, which writes a new version, activates it and revokes the previous one.
1# Attach to a connection created without one2curl -X POST "https://api.paycux.com/v1/environments/<environment id>/provider-connections/<connection id>/webhook-secret" \3 --cookie "__Host-paycux_session=<session cookie>" \4 -H "Content-Type: application/json" \5 -d '{ "projectId": "<project id>", "webhookSecret": "<signing secret>" }'67# Rotate an existing one8curl -X POST "https://api.paycux.com/v1/environments/<environment id>/provider-connections/<connection id>/rotate" \9 --cookie "__Host-paycux_session=<session cookie>" \10 -H "Content-Type: application/json" \11 -d '{ "projectId": "<project id>", "purpose": "webhook_signing", "value": "<new signing secret>" }'1213# 200 OK: "rotated": { "purpose": "webhook_signing", "version": 2, "previousRetirement": "complete" }
Map a plan to a provider price
A price mapping ties a catalog plan to a price id in your provider account through an active connection. Hosted checkout sells the highest mapped version of the plan key; a plan without a mapping answers 404 INVALID_SCOPE at checkout.
1curl -X POST "https://api.paycux.com/v1/environments/<environment id>/catalog/plans/<plan id>/price-mappings" \2 --cookie "__Host-paycux_session=<session cookie>" \3 -H "Content-Type: application/json" \4 -d '{ "projectId": "<project id>", "connectionId": "<connection id>", "providerPriceId": "<provider price id>" }'56# 201 Created7{8 "id": "<mapping id>",9 "planId": "<plan id>",10 "connectionId": "<connection id>",11 "providerPriceId": "<provider price id>",12 "createdAt": "2026-10-13T09:30:00.000Z"13}1415# 404 NOT_FOUND when the connection is not an active connection of this environment16# 409 CONFLICT when the provider price is already mapped on this connection
List connections
Any member role can read the list. It shows status and whether a signing secret is attached, and never a key.
1curl "https://api.paycux.com/v1/environments/<environment id>/provider-connections?projectId=<project id>" \2 --cookie "__Host-paycux_session=<session cookie>"34# 200 OK5{6 "items": [7 {8 "id": "<connection id>",9 "name": "paddle-sandbox",10 "provider": "paddle",11 "mode": "sandbox",12 "status": "active",13 "hasWebhookSecret": true,14 "createdAt": "2026-10-13T09:00:00.000Z",15 "updatedAt": "2026-10-13T09:20:00.000Z"16 }17 ]18}
Verify
Connect for real against a sandbox or test account, then break it on purpose. The pending state and the rotation are the parts worth seeing with your own eyes.
- 1Create a connection and confirm the response shows pending_webhook_verification and a webhook path, and no key.
- 2Register the path with the provider and send a test event. Confirm the connection is listed as active afterwards.
- 3Send an event signed with the wrong secret, or replay one, and confirm the connection's subscriptions are unchanged.
- 4Map a plan to a provider price and start a hosted checkout from your application. The session is created on your own provider account.
- 5Rotate the signing secret in Paycux, then at the provider, and confirm the next event still verifies. Rotate the API key with a value the provider rejects and confirm 400 PROVIDER_REJECTED with the old key still working.
Reference
Request and response shapes for each of these live in the API reference. Paths are relative to https://api.paycux.com.
| Method | Path | What it does |
|---|---|---|
| POST | /v1/environments/:environmentId/provider-connections | Create a connection to your own Stripe or Paddle account (console session; owner or admin). |
| GET | /v1/environments/:environmentId/provider-connections | List connections with status and hasWebhookSecret (console session; any role). Takes projectId. |
| POST | /v1/environments/:environmentId/provider-connections/:connectionId/webhook-secret | Attach a signing secret to a connection created without one (console session; owner or admin). |
| POST | /v1/environments/:environmentId/provider-connections/:connectionId/rotate | Rotate the api_key or webhook_signing secret as a new verified version (console session; owner or admin). |
| POST | /v1/environments/:environmentId/provider-connections/:connectionId/disable | Disable a connection; idempotent (console session; owner or admin). Takes projectId. |
| POST | /v1/environments/:environmentId/provider-connections/:connectionId/enable | Re-verify the stored key and set the status to active (console session; owner or admin). Takes projectId. |
| POST | /v1/environments/:environmentId/catalog/plans/:planId/price-mappings | Map a plan to a provider price on an active connection (console session; owner or admin). |
| POST | /v1/provider-connections/:connectionId/webhooks/stripe | Stripe webhook endpoint for the connection, verified with the provider signature over the raw body. |
| POST | /v1/provider-connections/:connectionId/webhooks/paddle | Paddle webhook endpoint for the connection, verified with the provider signature over the raw body. |