Let each business connect XRPay without sharing API keys
Add a Connect XRPay button to your software platform. Each customer business authorizes its own account; your server creates checkouts for that business, and a signed webhook returns the payment result with your order reference.
What the connected business keeps private
The connected-business flow
Use the same flow whether your customers run stores, hotels, clinics, schools, restaurants, field-service teams, creator businesses, or marketplace accounts. Each business approves a separate connection.
A business owner chooses Connect XRPay
Your platform creates state and PKCE values, then redirects the owner to XRPay.
XRPay shows the requested access
The owner signs in or registers, reviews each scope, and adds a settlement address if one is missing.
Your server receives a single-use code
XRPay returns the code to the exact registered callback URL. The code expires after five minutes.
Your server stores connected-account tokens
Exchange the code with the client secret and PKCE verifier. The business never copies an XRPay API key.
Your platform creates a hosted checkout
Send the order amount, currency, reference, line items, and one stable idempotency key.
The customer chooses an available payment method
XRPay shows the methods enabled for that business, country, currency, plan, and configured providers.
A signed event confirms the payment
Verify the raw-body signature, event ID, connection ID, amount, currency, and order reference before marking it paid.
Map the checkout to your product's record
1. Register the platform application
Open Dashboard → Platform Apps and create an application. Register the exact OAuth callback URL, a server-side payment webhook URL, and the maximum scopes the application may request.
Store the client secret on your server
| Scope | What it permits |
|---|---|
account.read | Read the connected business name, account status, and payment capabilities. |
checkout.write | Create XRPay-hosted checkout pages for that business. |
checkout.read | Read only the checkout sessions created through this connection. |
transaction.read | Read the payment amount, currency, status, and transaction reference. |
webhook.read | Receive signed events for payments created through this connection. |
2. Redirect the business owner to XRPay
Create a new state value and PKCE verifier for every connection attempt. Keep both in the signed-in user's server-side session and send only the S256 challenge to XRPay.
Production callback URLs must use HTTPS and match a registered URL exactly. HTTP is accepted only for localhost development. Use mode=test until the checkout and webhook paths pass your integration tests.
3. Exchange the five-minute authorization code
First compare the returned state with the value in the server-side session. Then exchange the code from your server with the same redirect URL and the original PKCE verifier.
The response includes a one-hour access token and a refresh token that expires after 90 days. The webhook signing secret appears only in the first code exchange response.
4. Read the business's available payment methods
Check capabilities after connection and before displaying payment settings in your product. The response reports XRP, RLUSD, cards, mobile money, other supported crypto, settlement, and payout separately.
Availability belongs to the connected business
5. Create one hosted checkout for the order
Create the checkout from your server. The idempotency key should describe one order payment attempt and remain unchanged when your server retries the same request.
A retry with the same connected account and Idempotency-Key returns the original checkout instead of creating a second payment. Metadata may be up to 10 KB and line items may contain up to 100 entries.
A browser return is not payment confirmation
6. Verify the signed payment event
XRPay signs the exact raw request body with HMAC-SHA256 and sends the value in X-XRPay-Signature. Parse JSON only after verifying the signature.
Store each webhook_id before applying a financial state change so a retry cannot mark the order paid twice. A connected application receives only events created through its connection.
7. Rotate the refresh token
Refresh before the one-hour access token expires or after an API request returns an expired-token authentication error. Every successful refresh returns a replacement refresh token and invalidates the previous value.
Endpoint reference
| Method | Path | Purpose |
|---|---|---|
GET | /connect/authorize | Ask the business owner to approve scopes. Requires state and S256 PKCE. |
POST | /api/connect/token | Exchange a code or rotate a refresh token. |
GET | /api/v1/connect/account | Read the connected account, scopes, mode, and connection status. |
GET | /api/v1/connect/capabilities | Read which payment methods are active or need setup. |
POST | /api/v1/sessions | Create one hosted checkout. Connected platforms must send Idempotency-Key. |
GET | /api/v1/sessions?id=… | Read a checkout created through the current connection. |
POST | /api/v1/connect/revoke | Revoke the current connection and invalidate its tokens. |
Errors your integration should handle
OAuth token errors use error and error_description. Authenticated API errors use an error object with a type and message.
| Error | What it means |
|---|---|
invalid_request | A required OAuth value is missing, state is shorter than 16 characters, or S256 PKCE is absent. |
invalid_client | The client ID is unavailable or client authentication failed. |
invalid_redirect_uri | The callback does not exactly match the registered HTTPS URL. |
invalid_scope | The request includes a scope the application is not configured to use. |
invalid_grant | The code or refresh token is invalid, expired, revoked, already used, or paired with the wrong verifier. |
access_denied | The business owner declined the connection. |
authentication_error | The API access token is missing, expired, invalid, or revoked. |
permission_error | The access token does not include the scope required by the endpoint. |
rate_limit_error | The platform exceeded the request limit returned in the response. |
Connection states
| State | What your platform should do |
|---|---|
active | Allow checkout creation and continue checking individual payment-method capabilities. |
setup_required | Show the requirement returned by the capability endpoint before enabling checkout. |
restricted | Stop checkout creation and direct the business owner to XRPay to resolve the account restriction. |
revoked | Delete stored access and refresh tokens, show Connect XRPay again, and require a new authorization. |
Business owners can revoke access from Dashboard → Connected Apps. Your platform can revoke its current connection with POST /api/v1/connect/revoke.
Before switching to live payments
- Complete the full authorization flow with mode=test.
- Confirm a retry with the same idempotency key returns the same checkout ID.
- Reject a webhook whose signature, connection ID, amount, currency, or order reference does not match.
- Store webhook IDs and prove that replaying the same event does not apply the payment twice.
- Rotate a refresh token and confirm the previous value no longer works.
- Revoke the connection from the XRPay dashboard and confirm both access and refresh tokens stop working.
Create the application
The platform account creates the application once. Each customer business then approves its own connection and keeps control of its XRPay account, settlement settings, and revocation.
Need help matching XRPay events to your order model? Send the callback URL, requested scopes, and test checkout flow to XRPay support.