Moosyl logo

Platform Connect

Let merchants connect their Moosyl account to your platform in a few clicks. You receive their API keys and a webhook, so you can take payments on their behalf.

Platform Connect is for platforms that take payments for other businesses: store builders, booking tools, marketplaces, POS apps. Instead of asking each merchant to copy API keys into your settings page, you send them to Moosyl, they approve the connection, and your server receives their credentials.

If you only take payments for your own business, you don't need Connect. Use your own API keys.

Get platform credentials

Platform credentials are issued by Moosyl. Contact us with your platform's name, and you'll receive:

  • a platform ID: public, used in the connect link
  • a platform secret: private, used only by your server

The platform secret is shown once. Store it like a password, in your server's secret store, never in frontend or mobile code.

How it works

Send the merchant to Moosyl

Redirect the merchant to the connect page:

https://moosyl.com/connect
  ?platform_id=YOUR_PLATFORM_ID
  &redirect_uri=https://yourplatform.com/moosyl/callback
  &state=RANDOM_STATE
  &environment=production
ParameterRequiredDescription
platform_idYesYour platform ID.
redirect_uriYesWhere Moosyl sends the merchant back. Must be an http or https URL.
stateNoA random value you generate per request. Moosyl returns it unchanged; check it on the callback.
environmentNosandbox (default) or production: which of the merchant's environments to connect.

If the merchant isn't signed in, Moosyl asks them to sign in first, then continues.

The merchant approves

Moosyl shows your platform's name and what it will be able to do: use the merchant's publishable and secret API keys for that environment, receive payment notifications at your webhook endpoint, and create payments on their behalf. The merchant can approve or deny.

Handle the callback

Moosyl redirects the merchant to your redirect_uri:

  • Approved: https://yourplatform.com/moosyl/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE
  • Denied: https://yourplatform.com/moosyl/callback?error=access_denied&state=RANDOM_STATE

Check that state matches the value you sent before doing anything else. The code is valid for 5 minutes and can be used once.

Exchange the code for credentials

From your server, exchange the code:

const res = await fetch("https://api.moosyl.com/connect/exchange", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    platform_id: process.env.MOOSYL_PLATFORM_ID,
    platform_secret: process.env.MOOSYL_PLATFORM_SECRET,
    code,
    // Receives both payment-created and payment-updated events
    webhook_payment_created_endpoint: "https://yourplatform.com/moosyl/webhooks",
  }),
});

const { data } = await res.json();
// data.connectionId, data.publishableKey, data.secretKey, data.webhookSecret

This endpoint doesn't use an Authorization header: your platform ID and secret authenticate the request.

The response:

{
  "data": {
    "connectionId": "7d2f0c1e-4b8a-4e59-9a6d-3c1b2e5f8a90",
    "publishableKey": "…",
    "secretKey": "…",
    "webhookSecret": "…"
  }
}

webhook_payment_updated_endpoint from earlier versions is still accepted but ignored: both events go to webhook_payment_created_endpoint. Route them on the x-webhook-event header or the event field.

What the merchant's connection gives you

  • connectionId: identifies this connection. Store it: you need it to disconnect.
  • publishableKey and secretKey: API keys created for your platform in the merchant's connected environment. The merchant sees them in their dashboard as "Connect: your platform name". Use them exactly like your own keys (see API keys and the Quickstart); every payment you create lands in the merchant's account.
  • A webhook in the merchant's environment, subscribed to payment-created and payment-updated, signed with webhookSecret. Verify it as described in Webhooks, using this webhookSecret.

Store these values per merchant, encrypted, on your server. The secretKey and webhookSecret must never reach a browser or mobile app.

Sandbox and production

A connection covers one environment. Connect with environment=sandbox while you build and test, then send the merchant through the flow again with environment=production when they go live. Each environment returns its own keys and webhook secret.

Reconnect a merchant

Sending a merchant through the flow again for the same environment keeps the same connectionId and webhook. The exchange returns new keys and a new webhook secret, and the previous keys stop working, so replace what you stored.

Disconnect a merchant

When a merchant leaves your platform, revoke the connection from your server:

await fetch("https://api.moosyl.com/connect/revoke", {
  method: "POST", // DELETE also works
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    platform_id: process.env.MOOSYL_PLATFORM_ID,
    platform_secret: process.env.MOOSYL_PLATFORM_SECRET,
    connection_id: connectionId,
  }),
});
// { "success": true }

Revoking deletes the connection's keys and webhook, so your platform loses access right away. Merchants can also disconnect your platform from Connected Apps in their dashboard, with the same effect. After that, the stored keys return 401 Invalid API key: treat that as a disconnected merchant.

Errors

Exchange and revoke fail with one of these:

StatusMessageWhat to do
404Platform app not foundCheck your platform_id, or contact us if your platform was deactivated.
403Invalid platform credentialsCheck your platform_secret.
404Invalid authorization codeThe code is wrong or belongs to another platform. Start the flow again.
400Authorization code has already been usedCodes are single-use. Start the flow again.
400Authorization code has expiredExchange codes within 5 minutes. Start the flow again.
404Connection not foundRevoke: the connection_id is wrong or belongs to another platform.

Security checklist

  • Generate a fresh, unguessable state for every connect link and reject callbacks where it doesn't match.
  • Exchange the code on your server only; the platform secret never leaves it.
  • Encrypt stored merchant credentials at rest and scope access to them per merchant.
  • Verify every webhook signature with that merchant's webhookSecret before trusting the event.
Platform Connect | Moosyl Docs