Docs

Start here

Getting started

Connect your backend to Paylor using API keys, stable references, and signed webhooks.

Authentication

Pass your secret key in the Authorization header for every server-to-server request. All requests must use HTTPS.

Authorization headerhttp
1Authorization: Bearer YOUR_API_KEY2Content-Type: application/json
Keep secret keys on your backend only. Public apps should call your backend, then your backend calls Paylor.
Authenticated requestjavascript
1import axios from 'axios';2 3const PAYLOR_API_KEY = process.env.PAYLOR_API_KEY;4const PAYLOR_BASE_URL = 'https://api.paylorke.com/api/v1';5 6const response = await axios.post(7  `${PAYLOR_BASE_URL}/merchants/payments/stk-push`,8  {9    phone: '254712345678',10    amount: 1000,11    reference: 'ORDER-12345',12    channelId: 'PAYL-XXXXXX',13    description: 'Payment for Service',14  },15  {16    headers: {17      'Authorization': `Bearer ${PAYLOR_API_KEY}`,18      'Content-Type': 'application/json',19    },20  }21);

Integration credentials

All credentials are available in your merchant dashboard under Developers > API Keys.

FieldUsageExample
Merchant IDYour unique account identifier used for internal reference.MERCH-A9X2Z...
API KeyYour active secret key (Bearer token). Keep this on your backend only.pk_xxxxxxxxxxxxxxxx
Webhook ID (Secret)A dedicated secret attached to your API key, shown as “Webhook ID (Secret)” in Developers > API Keys. Used to verify HMAC signatures on callbacks.6995fe04a1b2c3d4...
Channel ID / AliasThe unique alias of your payment channel (found in Settings).PAYL-XJ7K2P

API key scopes

Each API key carries scopes that control what it can do. Grant only what an integration needs. A key with global:* or crypto:* covers all actions in that product.

ScopeGrants
payments:createInitiate STK Push, B2B Express, and (fallback) crypto payments.
b2c:payoutSend M-Pesa B2C payouts.
transactions:readQuery and list transactions.
wallet:read / b2c:readRead wallet balance and B2C metrics.
channels:read|create|update|deleteManage payment channels.
crypto:create / crypto:readCreate and read USDT (TRC20) payments.
global:collectCreate Global collections, payment links, webhooks, and settings.
global:disburseCreate Global withdrawals (disbursements).
global:readRead Global wallet, ledger, providers, and listings.
Both dashboard sessions and API keys can call these endpoints. Sessions are unrestricted; API keys are limited to their granted scopes. A 403 with “Missing API key scope” means the key needs that scope.

Base URLs

Use the production API URL for live transactions. A sandbox environment is coming soon.

Production APIhttps://api.paylorke.com/api/v1
Sandboxhttps://api.paylorke.com/api/v1/sandbox (coming soon)

Idempotency and retries

Payment creation endpoints support idempotency keys. Sending the same key twice returns the original result instead of creating a duplicate transaction.

Idempotency headerhttp
1Idempotency-Key: order-12345-attempt-12# also accepted:3X-Idempotency-Key: order-12345-attempt-1

Reference

Use one stable reference per customer order, invoice, or withdrawal for reconciliation.

Idempotency-Key

Send a unique key per payment attempt and reuse it on network retries. Keys are capped at 180 characters.

Callback URL

Pass a callbackUrl per request or register a webhook endpoint in the dashboard.

Rate limits: payment endpoints allow 60 requests/minute; channel management endpoints allow 120 requests/minute. On 429 RATE_LIMIT_EXCEEDED, back off and retry with the same Idempotency-Key.

Error codes

Paylor uses conventional HTTP status codes. Every error response carries the same envelope with a machine-readable code, and validation errors include a per-field details array.

Error response envelopejson
1{2  "message": "Invalid request payload",3  "error": {4    "code": "VALIDATION_ERROR",5    "message": "Invalid request payload",6    "details": [7      {8        "path": "phone",9        "message": "phone is required",10        "code": "custom"11      }12    ]13  }14}
CodeDescription
400 VALIDATION_ERRORThe request body failed validation. The details array lists each invalid field.
400 INVALID_PHONE_NUMBERThe phone number is not a valid M-Pesa MSISDN. Use international format, e.g. 254712345678.
400 INVALID_AMOUNTThe amount is outside the allowed range for the endpoint.
401 UNAUTHORIZED / INVALID_API_KEYMissing or invalid Bearer token, or the key was revoked.
402 PAYMENT_REQUIREDInsufficient wallet balance to process the transaction or fee.
403 UNAUTHORIZEDThe API key is valid but is not authorized for this project or scope.
404 RESOURCE_NOT_FOUNDThe requested transaction, channel, or resource does not exist.
429 RATE_LIMIT_EXCEEDEDPayment endpoints allow 60 requests/minute; channel management allows 120.
500 INTERNAL_ERRORSomething failed on the Paylor side. Retry with the same reference and Idempotency-Key.

Best practices

Follow these rules to keep your integration reliable in production.

Trust webhooks, verify signatures

Update orders only from signed webhooks, and always recompute the HMAC signature before trusting a payload.

Query on doubt

If a webhook is missed, reconcile with the transaction query endpoint instead of assuming failure.

Rotate keys

Rotate API keys periodically and immediately if a key may have been exposed. Old keys are revoked on rotation.