API Reference
Authentication
API key headers, scoped OAuth and DPoP requests, permissions, rotation, and revocation.
Credential model
MakePay partner routes accept either a server API-key pair or a scoped OAuth access token. Both credential types resolve one MakeCrypto company on the server; callers must not supply a company ID to change that scope.
API keys are created from the MakeCrypto developer area and scoped to one team. Each key has a public key ID and a secret. The secret is stored as a hash and is shown only once after creation.
OAuth uses Authorization Code with PKCE. Access tokens are short lived and refresh tokens rotate on every use. Official native integrations register a public client per installation and receive DPoP-bound tokens, so possession of the access token alone is not enough to call MakePay APIs.
| Header | Value | Notes |
|---|---|---|
x-makecrypto-key-id | MakePay API key ID | Starts with mk_makepay_ for MakePay payment APIs. |
x-makecrypto-key-secret | One-time API secret | Shown only when the key is created. Store it in your server-side secret manager. |
API key creation
Signed-in users with settings.manage permission can create keys through the portal or through the team integration route.
Use the signed-in company discovery route when a portal tool needs to show the teams available to the current user:
GET /api/partner/v1/companies
The returned company id is used for dashboard/key-management routes only.
MakePay server-to-server payment routes resolve the company from the API key, so
they do not require a company ID in the URL.
POST /api/partner/v1/companies/{companyId}/integrations
Content-Type: application/json
{
"name": "Production backend",
"appSlug": "makepay",
"allowedOrigins": ["https://merchant.example"]
}
The response includes integration.key_id, integration.partner_id, and integration.keySecret. Save keySecret immediately.
OAuth authorization
For a partner application, register redirect URIs and allowed scopes in the MakeCrypto developer portal, then send the merchant through Authorization Code with PKCE. Official plugins such as the Medusa integration register a per-installation public client at:
POST https://www.makecrypto.io/oauth/native/installations
DPoP: <proof signed by the submitted public key>
Content-Type: application/json
Native registration requires an exact callback URI, an S256 PKCE challenge
during authorization, and proof that the installer possesses the private key
matching the submitted JWK thumbprint. Changing an existing installation to a
different key additionally requires DPoP-Previous, signed by the currently
registered key.
The Medusa registration payload is:
{
"platform": "medusa",
"registrationId": "2QEEnCWNzwDnLo6FCCjY0WtJxolIkJmLX1Yc5fVwawE",
"siteUrl": "https://api.shop.example",
"redirectUri": "https://api.shop.example/makepay/oauth/callback",
"dpopJkt": "BASE64URL_JWK_THUMBPRINT",
"medusaVersion": "2.17.2",
"pluginVersion": "1.0.0",
"siteName": "Example shop"
}
Generate registrationId once from 32 cryptographically random bytes, encode
it as canonical base64url without padding (exactly 43 characters), and persist
it before the first request. Reuse that same value for transport retries and
reconnects; it is the durable installation identity and is not derived from the
store URL.
siteUrl must be exactly one public HTTPS origin: no user info, path, query, or
fragment. redirectUri must be exactly that origin followed by
/makepay/oauth/callback; another path on the same host is not accepted. The
first successful registration returns 201; re-registering the same
installation returns 200. Both response forms identify a public, DPoP-bound
client and echo the accepted registration_id:
{
"client_id": "mco_app_...",
"client_type": "public",
"dpop_bound": true,
"registration_id": "2QEEnCWNzwDnLo6FCCjY0WtJxolIkJmLX1Yc5fVwawE",
"redirect_uri": "https://api.shop.example/makepay/oauth/callback",
"scopes": [
"company:read",
"makepay:payment-links:read",
"makepay:payment-links:write",
"makepay:webhooks:read",
"makepay:webhooks:write"
]
}
The response body has the same public fields for 201 and 200; the HTTP
status code indicates whether the installation was newly created. Both include
the client ID/type, DPoP binding, accepted registration ID, redirect URI, and
scope list.
The server derives the official name, icon, policies, and support links from
the immutable native-platform template. siteName and all other
caller-supplied metadata are support metadata only; they cannot change the app
branding shown on consent or Connected Apps screens.
Use the authorization, token, refresh, and revocation endpoints described in the OAuth applications guide. Never use a shared client secret in a distributable plugin.
Request authentication
For API-key authentication, send the key ID and secret as headers to MakePay partner routes.
x-makecrypto-key-id: mk_makepay_...
x-makecrypto-key-secret: mksec_...
For an unbound OAuth token, send the access token as a Bearer credential:
Authorization: Bearer <access-token>
For a native or otherwise DPoP-bound token, send the DPoP authorization scheme and a fresh proof for the exact HTTP method and URL:
Authorization: DPoP <access-token>
DPoP: <signed-proof-jwt>
The proof must use the key bound to the token, include a fresh jti, match the
request method and absolute URL, and include the access-token hash. Reusing a
proof or sending a DPoP-bound token as Bearer fails authentication.
In production, build the proof for the canonical
https://www.makecrypto.io/... URL and send the request there directly. Do not
build a proof for the apex host and follow its 307 redirect: the redirected
origin no longer matches the proof's htu claim.
The API also accepts signed-in MakeCrypto browser sessions for portal UI calls. Do not copy a browser session into an integration backend.
Permissions
API keys are trusted server credentials for their owning team. OAuth requests must include the scope required by the route. Common MakePay scopes are:
| Scope | Allows |
|---|---|
company:read | Read the selected company identity. |
makepay:payment-links:read | List and inspect payment links and status. |
makepay:payment-links:write | Create or update payment links. |
makepay:customers:read / write | Read or manage customer records. |
makepay:subscriptions:read / write | Read or manage subscription schedules. |
makepay:settings:read / write | Read or update merchant settings. |
makepay:webhooks:read / write | Read delivery state or manage the current grant's webhook subscription. |
Unknown scopes are rejected instead of being silently ignored. A token cannot gain scopes beyond the application allowlist and the merchant-approved grant. Signed-in browser mutations continue to require the corresponding team permission.
Rotation and revocation
For API keys, create a new key, deploy it to your backend, then disable or delete the old key in the MakeCrypto developer area. Existing secrets cannot be revealed again after creation.
For OAuth, persist each rotated refresh token atomically before discarding the previous value. Refresh-token reuse revokes the complete token family. Revoke or disconnect the grant when an installation is removed.
Native installation key rotation is staged separately from token rotation.
Registration proves possession of the submitted replacement key and requires
DPoP-Previous from the currently accepted key. Abandoning consent leaves the
old token family usable. If the pending replacement key is lost, the accepted
previous key can register another replacement. Successful consent binds the
grant to the new key and revokes the complete old access and refresh-token
family. MakeCrypto support is needed only when no accepted installation key
remains available.
Official Medusa installations do not expire because of inactivity. Their short-lived access tokens renew through the rotating refresh-token family, and the host plugin persists every rotation atomically. An access-token expiry is not a disconnected state, including after more than 30 days without a request. Explicit disconnect, revocation, a security reset, refresh-token reuse, or loss of the complete refresh family still terminates access. Other OAuth application templates retain their configured refresh-token lifetime.
If an official Medusa token request succeeds but its response is lost, retry the exact request with the same idempotency key. MakeCrypto serializes recovery with token issuance, successor use, grant revocation, and native reset, then revalidates the company, grant, scopes, DPoP binding, token family, and live successor after acquiring those locks. It never replays an older response after that successor has been used, revoked, or expired.
For an official Medusa installation, disconnect disables the subscription for new payment-link association but retains its immutable endpoint and encrypted signing secret only to authenticate late settlement for links already issued by that exact company, grant, subscription, and installation. A disabled non-Medusa OAuth subscription has no historical-delivery exception. Version 1.0.0 does not automatically purge a retained Medusa historical credential; the restricted database row remains encrypted and absent from Admin/API secret responses while referenced links or deliveries may still settle. Do not manually remove it independently of those records.
Authentication errors
401 Unauthorizedmeans the request has no valid session, API-key pair, or OAuth request.401 Invalid MakePay API credentialsalso covers an expired/revoked OAuth token, an inactive grant, a missing required scope, or an invalid/missing DPoP proof. Treat it as authentication failure and do not retry indefinitely.403 Forbiddenmeans the signed-in user cannot access the team or lacks the required permission.404 API key not foundis returned by key-management routes when the selectedpartnerIddoes not exist for the team.