Ummah
Payment Gateway API

A robust, developer-friendly REST API for integrating payments into your application. Built for e-commerce, subscriptions, and enterprise billing workflows.

Platform Integrations
WooCommerceOpenCart MagentoPHP PythonNode.js JavaiOS Android

Authentication

All API requests must include your secret key in the Authorization header using Bearer scheme.

Authorization: Bearer YOUR_SECRET_KEY
Test Mode — Use your sk_test_* key to make sandbox requests. No real payments are processed. Switch to sk_live_* for production.

API Keys

Retrieve your API keys from the dashboard under Settings → API Keys. Keep your secret key confidential — never expose it in client-side code.

Quickstart — Accept a Payment in 5 Minutes

Copy-paste this example into your project. Uses Node.js but the same flow applies to any language.

Install the SDK
npm install @ummah/payments
Initialize the client
Setup
# Set your key in the environment
export UMMAH_SECRET_KEY=sk_test_your_key_here
import Ummah from '@ummah/payments';

const ummah = new Ummah(process.env.UMMAH_SECRET_KEY);
import ummah
import os

client = ummah.Client(api_key=os.environ['UMMAH_SECRET_KEY'])
Create a purchase
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/" \
  -H "Authorization: Bearer $UMMAH_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
    "client": { "email": "user@example.com" },
    "purchase": {
      "products": [{ "name": "T-Shirt", "price": 5000, "quantity": 1 }],
      "currency": "USD"
    },
    "success_redirect": "https://yourapp.com/success",
    "failure_redirect": "https://yourapp.com/failure"
  }'
const purchase = await ummah.purchases.create({
  brand_id: '409eb80e-3782-4b1d-afa8-b779759266a5',
  client: { email: 'user@example.com' },
  purchase: {
    products: [{ name: 'T-Shirt', price: 5000, quantity: 1 }],
    currency: 'USD',
  },
  success_redirect: 'https://yourapp.com/success',
  failure_redirect: 'https://yourapp.com/failure',
});

console.log(purchase.checkout_url);
// → https://pay.ummah.com/checkout/pur_abc123
import requests, os

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/',
    headers={'Authorization': f'Bearer {os.environ["UMMAH_SECRET_KEY"]}'},
    json={
        'brand_id': '409eb80e-3782-4b1d-afa8-b779759266a5',
        'client': {'email': 'user@example.com'},
        'purchase': {
            'products': [{'name': 'T-Shirt', 'price': 5000, 'quantity': 1}],
            'currency': 'USD',
        },
        'success_redirect': 'https://yourapp.com/success',
        'failure_redirect': 'https://yourapp.com/failure',
    }
)
purchase = response.json()
print(purchase['checkout_url'])
Redirect your customer to checkout
Send the customer to purchase.checkout_url — a PCI-compliant hosted page. They enter their card details there; your server never handles raw card data.
Listen for the webhook
When payment completes, Ummah POSTs a purchase.paid event to your callback URL. Verify the X-Signature header and fulfill the order. See the Webhook Verification Guide.

Why Ummah

Ummah is purpose-built for businesses that require ethical, Shariah-aligned payment processing — without sacrificing the modern developer experience you expect from leading gateways.

FeatureUmmahStripe
Halal-compliant processing — no interest, no prohibited industries✓ Built-in✕ Not applicable
Shariah-aligned profit-sharing — revenue model reviewed by scholars✓ Yes✕ Conventional interest model
Built-in billing templates — reusable subscription plans✓ Native∼ Requires Stripe Billing add-on
Transparent, flat-rate pricing — one rate, no hidden fees✓ Yes∼ Tiered, plus add-on fees
Marketplace-ready — split payments between sellers✓ Roadmap✓ Stripe Connect
Hosted checkout (PCI DSS Level 1)✓ Yes✓ Yes
Multi-currency support✓ Yes✓ Yes
HMAC-SHA256 signed webhooks✓ Yes✓ Yes
Idempotency keys — safe request retries✓ Yes✓ Yes
Dedicated Muslim-majority market focus✓ Core mission✕ Not a focus
Roadmap note: Marketplace split payments are on our public roadmap for 2025. Contact us if this is a hard requirement — early access is available for select partners.

Core Objects

The API is built around five key objects that work together:

erDiagram
    PURCHASE ||--o{ CLIENT : "belongs to"
    PURCHASE }o--|| BRAND : "created for"
    BILLING_TEMPLATE ||--o{ SUBSCRIBER : "has"
    SUBSCRIBER ||--|| CLIENT : "is a"
    WEBHOOK ||--o{ DELIVERY : "sends"
🛒Purchase

The core transaction object. Holds product details, payment status, checkout URL, and client info.

👤Client

A customer record with contact details and optional saved payment methods (recurring tokens).

📋Billing Template

A reusable invoice or subscription plan. Generates purchases automatically for each subscriber.

Test Mode & Sandbox

Use your sk_test_* key to test the full API without processing real payments. All endpoints behave identically in test and live mode.

Test Card Numbers

Card NumberResultCVCExpiry
4242 4242 4242 4242SuccessAny 3 digitsAny future date
4000 0000 0000 0002DeclinedAny 3 digitsAny future date
4000 0000 0000 32203D Secure requiredAny 3 digitsAny future date
Sandbox only — Test cards only work with sk_test_* keys. Never use real card numbers in test mode.

Webhook Testing Tips

Use tools like ngrok to expose your local server for webhook testing. Set your callback URL to the ngrok tunnel URL during development.

Callbacks & Webhooks

When a payment event occurs, the gateway sends a signed POST request to your configured callback URL. Verify the X-Signature header using HMAC-SHA256 and your callback public key (see GET /public_key/).

Events

purchase.paidpurchase.payment_failurepurchase.refundedpurchase.cancelledbilling_template.client_activated

Best Practices

Return a 2xx response quickly to acknowledge receipt. Process the event asynchronously to avoid gateway timeout. The gateway retries failed deliveries.

Accept Payments

Accept Payments

Create purchases, redirect customers to checkout, and manage the full payment lifecycle — authorization, capture, refunds, and recurring charges.

Payment Flow

Every payment follows this lifecycle. Use skip_capture: true to authorize first and capture later.

stateDiagram-v2
    [*] --> Created: POST /purchases/
    Created --> Authorized: Customer pays (skip_capture)
    Created --> Paid: Customer pays
    Created --> Cancelled: POST /cancel/
    Authorized --> Paid: POST /capture/
    Authorized --> Released: POST /release/
    Paid --> Refunded: POST /refund/

Create a Purchase

POST/api/v1/purchases/

Register a new payment and receive a checkout_url to redirect your customer to. After payment, the gateway redirects back to your success_redirect / failure_redirect.

ParameterDescription
brand_idREQUIREDuuidID of the brand to create this Purchase for.
client.emailREQUIREDstringCustomer email address.
purchase.productsREQUIREDarrayProducts array. Each item: {name, price, quantity}.
purchase.currencyOPTIONALstring3-letter ISO currency code. Defaults to brand currency.
success_redirectOPTIONALstringURL to redirect to after successful payment.
failure_redirectOPTIONALstringURL to redirect to after payment failure.
success_callbackOPTIONALstringURL to POST a signed payment notification to.
skip_captureOPTIONALbooleanAuthorize only; capture funds later via POST /capture/.
force_recurringOPTIONALbooleanSave payment method for future recurring charges.
send_receiptOPTIONALbooleanEmail a receipt to the client after payment.
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
    "client": {
        "email": "customer@example.com"
    },
    "purchase": {
        "products": [
            {
                "name": "T-Shirt",
                "price": 2999,
                "quantity": 1
            }
        ],
        "currency": "USD"
    },
    "success_redirect": "https://myshop.com/success",
    "failure_redirect": "https://myshop.com/failed"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
  "client": {
    "email": "customer@example.com"
  },
  "purchase": {
    "products": [
      {
        "name": "T-Shirt",
        "price": 2999,
        "quantity": 1
      }
    ],
    "currency": "USD"
  },
  "success_redirect": "https://myshop.com/success",
  "failure_redirect": "https://myshop.com/failed"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
    'brand_id': '409eb80e-3782-4b1d-afa8-b779759266a5',
    'client': {'email': 'customer@example.com'},
    'purchase': {
        'products': [{'name': 'T-Shirt', 'price': 2999, 'quantity': 1}],
        'currency': 'USD',
    },
    'success_redirect': 'https://myshop.com/success',
    'failure_redirect': 'https://myshop.com/failed',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/',
    headers=headers,
    json=data
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
      "client": {
        "email": "customer@example.com"
      },
      "purchase": {
        "products": [
          {
            "name": "T-Shirt",
            "price": 2999,
            "quantity": 1
          }
        ],
        "currency": "USD"
      },
      "success_redirect": "https://myshop.com/success",
      "failure_redirect": "https://myshop.com/failed"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "created",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "invoice_url": "https://pay.ummah.com/invoice/d6c9...",
  "client": { "email": "customer@example.com", "full_name": "John Doe" },
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Retrieve a Purchase

GET/api/v1/purchases/{id}/

Retrieve the full details of a purchase by its ID, including current status, payment data, and client info.

Request
curl -X GET "https://gate.ummah.com/api/v1/purchases/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/purchases/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/purchases/{id}/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/purchases/{id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "paid",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "payment": { "method": "card", "is_recurring_token": false },
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Cancel a Purchase

POST/api/v1/purchases/{id}/cancel/

Cancel a pending or authorized purchase. Only purchases in created or authorized status can be cancelled.

Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/cancel/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/cancel/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/cancel/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/cancel/',
    headers=headers
)

print(response.json())
Response
{"status": "cancelled"}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Void Authorization

POST/api/v1/purchases/{id}/release/

Release funds that were authorized (held) on a purchase with skip_capture: true. This voids the authorization without capturing.

Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/release/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/release/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/release/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/release/',
    headers=headers
)

print(response.json())
Response
{"status": "released"}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Capture a Purchase

POST/api/v1/purchases/{id}/capture/

Capture a previously authorized purchase. Optionally specify a partial amount in the smallest currency unit.

ParameterDescription
amountOPTIONALintegerAmount to capture in smallest currency unit (e.g. cents). Defaults to full authorized amount.
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/capture/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "amount": 2999
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "amount": 2999
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/capture/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {'amount': 2999}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/capture/',
    headers=headers,
    json=data
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "amount": 2999
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/capture/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "paid",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "payment": { "method": "card", "is_recurring_token": false },
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Charge Saved Payment Method

POST/api/v1/purchases/{id}/charge/

Charge or hold a purchase using a saved recurring token. Use this for subscription renewals or one-click payments.

ParameterDescription
recurring_tokenOPTIONALstringID of the recurring token to charge.
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/charge/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "recurring_token": "tok-a1b2c3d4-e5f6-7890"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "recurring_token": "tok-a1b2c3d4-e5f6-7890"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/charge/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {'recurring_token': 'tok-a1b2c3d4-e5f6-7890'}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/charge/',
    headers=headers,
    json=data
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "recurring_token": "tok-a1b2c3d4-e5f6-7890"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/charge/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "paid",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "payment": { "method": "card", "is_recurring_token": false },
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Refund a Purchase

POST/api/v1/purchases/{id}/refund/

Refund a paid purchase in full or partially. Optionally pass an internal reference for your records.

ParameterDescription
amountOPTIONALintegerAmount to refund in smallest currency unit. Defaults to full amount.
referenceOPTIONALstringInternal refund reference for your records.
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/refund/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "amount": 1500,
    "reference": "REFUND-2024-001"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "amount": 1500,
  "reference": "REFUND-2024-001"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/refund/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
    'amount': 1500,
    'reference': 'REFUND-2024-001',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/refund/',
    headers=headers,
    json=data
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "amount": 1500,
      "reference": "REFUND-2024-001"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/refund/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "paid",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "payment": { "method": "card", "is_recurring_token": false },
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Confirm Offline Payment

POST/api/v1/purchases/{id}/mark_as_paid/

Manually mark a purchase as paid. Useful for cash/offline payments recorded in the system.

ParameterDescription
paid_onOPTIONALtimestampUnix timestamp of when payment was received. Defaults to now.
Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/mark_as_paid/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "paid_on": 1700000000
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "paid_on": 1700000000
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/mark_as_paid/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {'paid_on': 1700000000}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/mark_as_paid/',
    headers=headers,
    json=data
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "paid_on": 1700000000
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/mark_as_paid/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "paid",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "payment": { "method": "card", "is_recurring_token": false },
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Resend Invoice Email

POST/api/v1/purchases/{id}/resend_invoice/

Re-sends the invoice email for this purchase to the client.

Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/resend_invoice/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/resend_invoice/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/resend_invoice/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/resend_invoice/',
    headers=headers
)

print(response.json())
Response
{"status": "sent"}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Detach Payment Method

POST/api/v1/purchases/{id}/delete_recurring_token/

Delete the recurring token associated with this purchase, preventing future recurring charges.

Request
curl -X POST "https://gate.ummah.com/api/v1/purchases/{id}/delete_recurring_token/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/purchases/{id}/delete_recurring_token/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/delete_recurring_token/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/purchases/{id}/delete_recurring_token/',
    headers=headers
)

print(response.json())
Response
{"status": "deleted"}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

List Payment Methods

GET/api/v1/payment_methods/

Get the list of payment methods available for your purchase, filtered by country and currency.

Request
curl -X GET "https://gate.ummah.com/api/v1/payment_methods/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/payment_methods/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/payment_methods/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/payment_methods/',
    headers=headers
)

print(response.json())
Response
{
  "payment_methods": [
    { "name": "card", "countries": ["US", "GB", "AE"], "currencies": ["USD", "GBP", "AED"] },
    { "name": "apple_pay", "countries": ["US", "GB"], "currencies": ["USD", "GBP"] }
  ]
}

List Payout Methods

GET/api/v1/payout_methods/

Get the list of payout methods available for your brand.

Request
curl -X GET "https://gate.ummah.com/api/v1/payout_methods/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/payout_methods/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/payout_methods/',
    headers=headers
)

print(response.json())
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/payout_methods/',
    headers=headers
)

print(response.json())
Response
{"payout_methods": [{"name": "bank_transfer", "countries": ["US","GB"], "currencies": ["USD","GBP"]}]}
Subscriptions

Recurring Billing

Create billing templates for subscription plans, add subscribers, and let the gateway handle automatic renewal charges on your schedule.

Subscription Lifecycle

Subscribers progress through these states. Use the template client endpoints to pause or resume billing.

stateDiagram-v2
    [*] --> Template: POST /billing_templates/
    Template --> Subscriber: POST /add_subscriber/
    Subscriber --> Active: First payment
    Active --> Renewal: Billing cycle
    Renewal --> Active: Payment success
    Renewal --> Failed: Payment failure
    Active --> Paused: PATCH status=paused
    Paused --> Active: PATCH status=active
Invoicing

One-Time Invoicing

Send invoices directly to clients or generate them from billing templates. Each client receives a unique checkout link.

Send an Invoice

POST/api/v1/billing/

Send a one-time invoice to one or several clients. Each client receives a unique checkout/invoice link.

ParameterDescription
brand_idREQUIREDuuidID of the brand issuing the invoice.
clientsREQUIREDarrayArray of client objects or client IDs to invoice.
purchase.productsREQUIREDarrayProducts to include in the invoice.
purchase.currencyOPTIONALstring3-letter ISO currency code.
Request
curl -X POST "https://gate.ummah.com/api/v1/billing/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": "409eb80e-...",
    "clients": [
        {
            "email": "client@example.com"
        }
    ],
    "purchase": {
        "products": [
            {
                "name": "Consulting",
                "price": 50000
            }
        ],
        "currency": "USD"
    }
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "brand_id": "409eb80e-...",
  "clients": [
    {
      "email": "client@example.com"
    }
  ],
  "purchase": {
    "products": [
      {
        "name": "Consulting",
        "price": 50000
      }
    ],
    "currency": "USD"
  }
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/billing/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "brand_id": "409eb80e-...",
      "clients": [
        {
          "email": "client@example.com"
        }
      ],
      "purchase": {
        "products": [
          {
            "name": "Consulting",
            "price": 50000
          }
        ],
        "currency": "USD"
      }
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/billing/',
    headers=headers,
    json=data
)

print(response.json())
Response
[{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "created",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "invoice_url": "https://pay.ummah.com/invoice/d6c9...",
  "client": { "email": "customer@example.com", "full_name": "John Doe" },
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "created_on": 1700000000
}]
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Create Billing Template

POST/api/v1/billing_templates/

Create a reusable billing template for one-time invoices or recurring subscriptions. Set is_subscription: true and specify subscription_period for recurring billing.

ParameterDescription
purchaseREQUIREDobjectPurchaseDetails object: products, currency, etc.
is_subscriptionREQUIREDbooleantrue for subscription, false for one-time invoicing.
brand_idREQUIREDuuidID of the brand for this template.
subscription_periodOPTIONALstringBilling period: day, week, month, year.
number_of_billing_cyclesOPTIONALintegerLimit billing cycles per client. 0 = unlimited.
Request
curl -X POST "https://gate.ummah.com/api/v1/billing_templates/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "brand_id": "409eb80e-...",
    "is_subscription": true,
    "purchase": {
        "products": [
            {
                "name": "Monthly Plan",
                "price": 999
            }
        ],
        "currency": "USD"
    },
    "subscription_period": "month"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "brand_id": "409eb80e-...",
  "is_subscription": true,
  "purchase": {
    "products": [
      {
        "name": "Monthly Plan",
        "price": 999
      }
    ],
    "currency": "USD"
  },
  "subscription_period": "month"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/billing_templates/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "brand_id": "409eb80e-...",
      "is_subscription": True,
      "purchase": {
        "products": [
          {
            "name": "Monthly Plan",
            "price": 999
          }
        ],
        "currency": "USD"
      },
      "subscription_period": "month"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/billing_templates/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "bt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "is_subscription": true,
  "purchase": { "currency": "USD", "total_amount": 999 },
  "subscription_period": "month",
  "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

List Billing Templates

GET/api/v1/billing_templates/

List all billing templates for your account.

Request
curl -X GET "https://gate.ummah.com/api/v1/billing_templates/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/billing_templates/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/billing_templates/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "bt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "is_subscription": true,
  "purchase": { "currency": "USD", "total_amount": 999 },
  "subscription_period": "month",
  "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
  "created_on": 1700000000
}]

Retrieve Billing Template

GET/api/v1/billing_templates/{id}/

Retrieve a billing template by its ID.

Request
curl -X GET "https://gate.ummah.com/api/v1/billing_templates/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "bt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "is_subscription": true,
  "purchase": { "currency": "USD", "total_amount": 999 },
  "subscription_period": "month",
  "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Update Billing Template

PUT/api/v1/billing_templates/{id}/

Replace all fields of a billing template.

ParameterDescription
purchaseREQUIREDobjectUpdated PurchaseDetails object.
is_subscriptionREQUIREDbooleanSubscription mode flag.
Request
curl -X PUT "https://gate.ummah.com/api/v1/billing_templates/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "purchase": {
        "products": [
            {
                "name": "Updated Plan",
                "price": 1299
            }
        ],
        "currency": "USD"
    },
    "is_subscription": true
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "purchase": {
    "products": [
      {
        "name": "Updated Plan",
        "price": 1299
      }
    ],
    "currency": "USD"
  },
  "is_subscription": true
};

const { data: result } = await axios.put(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "purchase": {
        "products": [
          {
            "name": "Updated Plan",
            "price": 1299
          }
        ],
        "currency": "USD"
      },
      "is_subscription": True
    }

response = requests.put(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "bt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "is_subscription": true,
  "purchase": { "currency": "USD", "total_amount": 999 },
  "subscription_period": "month",
  "brand_id": "409eb80e-3782-4b1d-afa8-b779759266a5",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Delete Billing Template

DELETE/api/v1/billing_templates/{id}/

Delete a billing template by its ID. This does not cancel active subscriptions.

Request
curl -X DELETE "https://gate.ummah.com/api/v1/billing_templates/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.delete(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.delete(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/',
    headers=headers
)

print(response.status_code)
Response
(empty — 204 No Content)
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Send Invoice from Template

POST/api/v1/billing_templates/{id}/send_invoice/

Send an invoice by generating a purchase from the template's data. Pass client details to generate a unique invoice for them.

ParameterDescription
clientOPTIONALobjectClient details (email, full_name, etc.).
client_idOPTIONALuuidID of an existing Client object.
Request
curl -X POST "https://gate.ummah.com/api/v1/billing_templates/{id}/send_invoice/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "client": {
        "email": "client@example.com",
        "full_name": "John Doe"
    }
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "client": {
    "email": "client@example.com",
    "full_name": "John Doe"
  }
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/send_invoice/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "client": {
        "email": "client@example.com",
        "full_name": "John Doe"
      }
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/send_invoice/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "d6c9e9e0-1b5a-4c6e-8b3a-0f1a2b3c4d5e",
  "status": "created",
  "checkout_url": "https://pay.ummah.com/checkout/d6c9...",
  "invoice_url": "https://pay.ummah.com/invoice/d6c9...",
  "client": { "email": "customer@example.com", "full_name": "John Doe" },
  "purchase": { "total_amount": 2999, "currency": "USD" },
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Subscribe

POST/api/v1/billing_templates/{id}/add_subscriber/

Add a client to a subscription billing template. This activates their recurring billing cycle.

ParameterDescription
clientOPTIONALobjectClient details for the subscriber.
client_idOPTIONALuuidID of an existing Client to subscribe.
Request
curl -X POST "https://gate.ummah.com/api/v1/billing_templates/{id}/add_subscriber/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "client": {
        "email": "subscriber@example.com"
    }
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "client": {
    "email": "subscriber@example.com"
  }
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/add_subscriber/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "client": {
        "email": "subscriber@example.com"
      }
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/add_subscriber/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "btc-a1b2c3d4-e5f6-7890",
  "client": { "email": "subscriber@example.com" },
  "is_subscription": true,
  "status": "active",
  "next_billing_on": 1703000000,
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

List Subscribers

GET/api/v1/billing_templates/{id}/clients/

List all billing template clients (subscribers) associated with this template.

Request
curl -X GET "https://gate.ummah.com/api/v1/billing_templates/{id}/clients/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "btc-a1b2c3d4-e5f6-7890",
  "client": { "email": "subscriber@example.com" },
  "is_subscription": true,
  "status": "active",
  "next_billing_on": 1703000000,
  "created_on": 1700000000
}]

Get Subscriber

GET/api/v1/billing_templates/{id}/clients/{client_id}/

Retrieve details of a specific billing template client by their ID.

Request
curl -X GET "https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "btc-a1b2c3d4-e5f6-7890",
  "client": { "email": "subscriber@example.com" },
  "is_subscription": true,
  "status": "active",
  "next_billing_on": 1703000000,
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Update Subscriber

PATCH/api/v1/billing_templates/{id}/clients/{client_id}/

Partially update a billing template client — for example, pause or resume their subscription.

ParameterDescription
statusOPTIONALstringSubscription status: active or paused.
Request
curl -X PATCH "https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "status": "paused"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "status": "paused"
};

const { data: result } = await axios.patch(
  'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "status": "paused"
    }

response = requests.patch(
    'https://gate.ummah.com/api/v1/billing_templates/{id}/clients/{client_id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "btc-a1b2c3d4-e5f6-7890",
  "client": { "email": "subscriber@example.com" },
  "is_subscription": true,
  "status": "active",
  "next_billing_on": 1703000000,
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}
Customers & Cards

Customer Management

Create and manage customer records with saved payment methods. Use recurring tokens for one-click payments and subscription renewals.

Create a Client

POST/api/v1/clients/

Create a new client record to store customer contact information.

ParameterDescription
emailREQUIREDstring (email)Client email address.
full_nameOPTIONALstringClient full name.
phoneOPTIONALstringClient phone number in E.164 format.
street_addressOPTIONALstringBilling street address.
countryOPTIONALstring2-letter ISO country code.
cityOPTIONALstringCity.
zip_codeOPTIONALstringZIP / postal code.
Request
curl -X POST "https://gate.ummah.com/api/v1/clients/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "email": "client@example.com",
    "full_name": "John Doe",
    "phone": "+1234567890",
    "country": "US"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/clients/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "email": "client@example.com",
      "full_name": "John Doe",
      "phone": "+1234567890",
      "country": "US"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/clients/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "c1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6",
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US",
  "type": "personal",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

List Clients

GET/api/v1/clients/

Retrieve a paginated list of all client records for your account.

Request
curl -X GET "https://gate.ummah.com/api/v1/clients/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/clients/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/clients/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "c1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6",
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US",
  "type": "personal",
  "created_on": 1700000000
}]

Retrieve a Client

GET/api/v1/clients/{id}/

Retrieve a specific client by their ID.

Request
curl -X GET "https://gate.ummah.com/api/v1/clients/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/clients/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/clients/{id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "c1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6",
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US",
  "type": "personal",
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Update a Client

PUT/api/v1/clients/{id}/

Replace all fields of a client record.

ParameterDescription
emailREQUIREDstringClient email address.
Request
curl -X PUT "https://gate.ummah.com/api/v1/clients/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "email": "updated@example.com",
    "full_name": "Jane Doe",
    "country": "GB"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "email": "updated@example.com",
  "full_name": "Jane Doe",
  "country": "GB"
};

const { data: result } = await axios.put(
  'https://gate.ummah.com/api/v1/clients/{id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "email": "updated@example.com",
      "full_name": "Jane Doe",
      "country": "GB"
    }

response = requests.put(
    'https://gate.ummah.com/api/v1/clients/{id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "c1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6",
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US",
  "type": "personal",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Partially Update a Client

PATCH/api/v1/clients/{id}/

Update specific fields of a client record without replacing the entire object.

Request
curl -X PATCH "https://gate.ummah.com/api/v1/clients/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "full_name": "Updated Name"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "full_name": "Updated Name"
};

const { data: result } = await axios.patch(
  'https://gate.ummah.com/api/v1/clients/{id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "full_name": "Updated Name"
    }

response = requests.patch(
    'https://gate.ummah.com/api/v1/clients/{id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "c1a2b3c4-d5e6-f7a8-b9c0-d1e2f3a4b5c6",
  "email": "client@example.com",
  "full_name": "John Doe",
  "phone": "+1234567890",
  "country": "US",
  "type": "personal",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Delete a Client

DELETE/api/v1/clients/{id}/

Permanently delete a client record and their associated data.

Request
curl -X DELETE "https://gate.ummah.com/api/v1/clients/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.delete(
  'https://gate.ummah.com/api/v1/clients/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.delete(
    'https://gate.ummah.com/api/v1/clients/{id}/',
    headers=headers
)

print(response.status_code)
Response
(empty — 204 No Content)
{"error": "Not Found", "detail": "Object with this ID does not exist."}

List Payment Methods

GET/api/v1/clients/{id}/recurring_tokens/

List all saved recurring payment tokens for a client (e.g. saved card tokens).

Request
curl -X GET "https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "tok-a1b2c3d4-e5f6-7890",
  "payment_method": "card",
  "description": "Visa **** 4242",
  "created_on": 1700000000
}]

Get Payment Method

GET/api/v1/clients/{id}/recurring_tokens/{token_id}/

Retrieve a specific recurring payment token by its ID.

Request
curl -X GET "https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "tok-a1b2c3d4-e5f6-7890",
  "payment_method": "card",
  "description": "Visa **** 4242",
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Delete Payment Method

DELETE/api/v1/clients/{id}/recurring_tokens/{token_id}/

Delete a saved recurring token, preventing it from being used for future charges.

Request
curl -X DELETE "https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.delete(
  'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.delete(
    'https://gate.ummah.com/api/v1/clients/{id}/recurring_tokens/{token_id}/',
    headers=headers
)

print(response.status_code)
Response
(empty — 204 No Content)
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Webhook Verification Guide

Every webhook delivery includes an X-Signature header containing an HMAC-SHA256 digest of the raw request body, signed with your webhook secret. Always verify this header before processing any event.

Step 1 — Retrieve your webhook secret
Go to Dashboard → Webhooks → Settings and copy the signing secret (starts with whsec_). Store it in an environment variable.
Step 2 — Read the raw request body
You must use the raw (un-parsed) bytes for signature verification. Parsing the body first (e.g. with express.json()) will change whitespace and break the signature check.
Step 3 — Compute and compare the HMAC
Compute HMAC-SHA256(rawBody, webhookSecret) and compare it to the value in the X-Signature header using a constant-time comparison to prevent timing attacks.
Step 4 — Respond with 200 OK
Return HTTP 200 immediately after verification. If your handler takes too long, the gateway will retry the delivery. Process heavy logic asynchronously.
Webhook Handler
const express = require('express');
const crypto  = require('crypto');

const app    = express();
const SECRET = process.env.WEBHOOK_SECRET; // whsec_...

// IMPORTANT: use raw body parser — do NOT use express.json() here
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sigHeader  = req.headers['x-signature'];
  const rawBody    = req.body; // Buffer

  const expected = crypto
    .createHmac('sha256', SECRET)
    .update(rawBody)
    .digest('hex');

  const trusted = crypto.timingSafeEqual(
    Buffer.from(expected),
    Buffer.from(sigHeader)
  );

  if (!trusted) {
    return res.status(403).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(rawBody);
  console.log('Event received:', event.type);

  // Handle event types
  switch (event.type) {
    case 'purchase.paid':
      // fulfil the order
      break;
    case 'purchase.failed':
      // notify the customer
      break;
    default:
      console.log('Unhandled event type:', event.type);
  }

  res.sendStatus(200);
});

app.listen(3000);
import hmac
import hashlib
import os
from flask import Flask, request, abort

app    = Flask(__name__)
SECRET = os.environ['WEBHOOK_SECRET'].encode()  # whsec_...

@app.route('/webhook', methods=['POST'])
def webhook():
    sig_header = request.headers.get('X-Signature', '')
    raw_body   = request.get_data()  # raw bytes — do NOT use request.json here

    expected = hmac.new(SECRET, raw_body, hashlib.sha256).hexdigest()

    if not hmac.compare_digest(expected, sig_header):
        abort(403)

    event = request.get_json(force=True)
    print('Event received:', event.get('type'))

    # Handle event types
    if event['type'] == 'purchase.paid':
        pass  # fulfil the order
    elif event['type'] == 'purchase.failed':
        pass  # notify the customer

    return '', 200

if __name__ == '__main__':
    app.run(port=3000)
<?php

$secret  = getenv('WEBHOOK_SECRET'); // whsec_...
$payload = file_get_contents('php://input'); // raw body
$sigHeader = $_SERVER['HTTP_X_SIGNATURE'] ?? '';

$expected = hash_hmac('sha256', $payload, $secret);

if (!hash_equals($expected, $sigHeader)) {
    http_response_code(403);
    echo json_encode(['error' => 'Invalid signature']);
    exit;
}

$event = json_decode($payload, true);
error_log('Event received: ' . $event['type']);

switch ($event['type']) {
    case 'purchase.paid':
        // fulfil the order
        break;
    case 'purchase.failed':
        // notify the customer
        break;
    default:
        error_log('Unhandled event: ' . $event['type']);
}

http_response_code(200);

Security Best Practices

Follow these guidelines to keep your integration secure:

Verify every callback
Always validate the X-Signature header using your public key. Never trust unverified payloads.
Use HTTPS everywhere
All callback URLs must use HTTPS. The gateway rejects plain HTTP endpoints.
Protect your secret key
Store sk_live_* keys in environment variables. Never commit them to source control or expose in client-side code.
Implement idempotency
Webhook deliveries may be retried. Use the purchase id to deduplicate events and prevent double-processing.
Webhooks & Security

Webhook Endpoints

Register webhook endpoints to receive real-time notifications. The gateway signs each delivery with HMAC-SHA256 so you can verify authenticity.

Create a Webhook

POST/api/v1/webhooks/

Register a new webhook endpoint to receive event notifications.

ParameterDescription
callbackREQUIREDstring (url)HTTPS URL to POST event payloads to.
titleOPTIONALstringFriendly name for this webhook.
eventsOPTIONALarrayList of event types to subscribe to. e.g. ["purchase.paid"].
all_eventsOPTIONALbooleanSet to true to receive all event types.
Request
curl -X POST "https://gate.ummah.com/api/v1/webhooks/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "callback": "https://mysite.com/webhook",
    "title": "Order Notifications",
    "events": [
        "purchase.paid",
        "purchase.payment_failure"
    ]
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "callback": "https://mysite.com/webhook",
  "title": "Order Notifications",
  "events": [
    "purchase.paid",
    "purchase.payment_failure"
  ]
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/webhooks/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "callback": "https://mysite.com/webhook",
      "title": "Order Notifications",
      "events": [
        "purchase.paid",
        "purchase.payment_failure"
      ]
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/webhooks/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "My Webhook",
  "callback": "https://mysite.com/webhook",
  "events": ["purchase.paid", "purchase.payment_failure"],
  "all_events": false,
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

List Webhooks

GET/api/v1/webhooks/

Retrieve all registered webhook endpoints for your account.

Request
curl -X GET "https://gate.ummah.com/api/v1/webhooks/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/webhooks/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/webhooks/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "My Webhook",
  "callback": "https://mysite.com/webhook",
  "events": ["purchase.paid", "purchase.payment_failure"],
  "all_events": false,
  "created_on": 1700000000
}]

Retrieve a Webhook

GET/api/v1/webhooks/{id}/

Retrieve a specific webhook by its ID.

Request
curl -X GET "https://gate.ummah.com/api/v1/webhooks/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/webhooks/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/webhooks/{id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "My Webhook",
  "callback": "https://mysite.com/webhook",
  "events": ["purchase.paid", "purchase.payment_failure"],
  "all_events": false,
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Update a Webhook

PUT/api/v1/webhooks/{id}/

Replace all fields of a webhook endpoint.

Request
curl -X PUT "https://gate.ummah.com/api/v1/webhooks/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "callback": "https://mysite.com/new-webhook",
    "title": "Updated Webhook",
    "all_events": true
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "callback": "https://mysite.com/new-webhook",
  "title": "Updated Webhook",
  "all_events": true
};

const { data: result } = await axios.put(
  'https://gate.ummah.com/api/v1/webhooks/{id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "callback": "https://mysite.com/new-webhook",
      "title": "Updated Webhook",
      "all_events": True
    }

response = requests.put(
    'https://gate.ummah.com/api/v1/webhooks/{id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "My Webhook",
  "callback": "https://mysite.com/webhook",
  "events": ["purchase.paid", "purchase.payment_failure"],
  "all_events": false,
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Partially Update a Webhook

PATCH/api/v1/webhooks/{id}/

Update specific fields of a webhook endpoint.

Request
curl -X PATCH "https://gate.ummah.com/api/v1/webhooks/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "title": "Renamed Webhook"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "title": "Renamed Webhook"
};

const { data: result } = await axios.patch(
  'https://gate.ummah.com/api/v1/webhooks/{id}/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "title": "Renamed Webhook"
    }

response = requests.patch(
    'https://gate.ummah.com/api/v1/webhooks/{id}/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "wh-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "title": "My Webhook",
  "callback": "https://mysite.com/webhook",
  "events": ["purchase.paid", "purchase.payment_failure"],
  "all_events": false,
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

Delete a Webhook

DELETE/api/v1/webhooks/{id}/

Delete a webhook endpoint. No further deliveries will be sent.

Request
curl -X DELETE "https://gate.ummah.com/api/v1/webhooks/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.delete(
  'https://gate.ummah.com/api/v1/webhooks/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.delete(
    'https://gate.ummah.com/api/v1/webhooks/{id}/',
    headers=headers
)

print(response.status_code)
Response
(empty — 204 No Content)
{"error": "Not Found", "detail": "Object with this ID does not exist."}

List Webhook Deliveries

GET/api/v1/webhooks/deliveries/

List recent webhook delivery attempts, including response codes and payloads. Useful for debugging missed events.

Request
curl -X GET "https://gate.ummah.com/api/v1/webhooks/deliveries/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/webhooks/deliveries/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/webhooks/deliveries/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "wh-delivery-a1b2",
  "event": "purchase.paid",
  "status": "delivered",
  "response_code": 200,
  "sent_at": 1700001234,
  "payload": { "event": "purchase.paid", "object": { "id": "d6c9..." } }
}]
Reporting & Payouts

Reporting & Financials

Access real-time balance data, transaction turnover reports, and generate downloadable financial statements in CSV or XLSX format.

Company Balance

GET/api/v1/account/json/balance/

Get the current balance of your company account, broken down by currency.

Request
curl -X GET "https://gate.ummah.com/api/v1/account/json/balance/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/account/json/balance/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/account/json/balance/',
    headers=headers
)

print(response.json())
Response
{
  "balance": [
    { "currency": "USD", "amount": 125000 },
    { "currency": "EUR", "amount": 87500 }
  ]
}

Company Turnover

GET/api/v1/account/json/turnover/

Get transaction turnover data for your company, grouped by currency and time period.

Request
curl -X GET "https://gate.ummah.com/api/v1/account/json/turnover/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/account/json/turnover/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/account/json/turnover/',
    headers=headers
)

print(response.json())
Response
{
  "turnover": [
    { "currency": "USD", "paid_amount": 1250000, "period": "2024-01" },
    { "currency": "USD", "paid_amount": 980000,  "period": "2024-02" }
  ]
}

Get Balance Data

GET/api/v1/balance/

Retrieve detailed balance data for your account.

Request
curl -X GET "https://gate.ummah.com/api/v1/balance/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/balance/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/balance/',
    headers=headers
)

print(response.json())
Response
{
  "balance": [
    { "currency": "USD", "amount": 125000 },
    { "currency": "EUR", "amount": 87500 }
  ]
}

Schedule Statement Generation

POST/api/v1/company_statements/

Schedule a financial statement for generation. Once processing completes, a download_url becomes available.

ParameterDescription
formatREQUIREDstringOutput format: csv or xlsx.
timezoneOPTIONALstringTimezone for timestamps, e.g. UTC, Asia/Dubai.
query_stringOPTIONALstringQuery parameters to filter statement data.
Request
curl -X POST "https://gate.ummah.com/api/v1/company_statements/" \
  -H "Authorization: Bearer $SECRET_KEY"
  -H "Content-Type: application/json" \
  -d '{
    "format": "csv",
    "timezone": "UTC"
}'
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const data = {
  "format": "csv",
  "timezone": "UTC"
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/company_statements/',
  data,
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
    'Content-Type': 'application/json',
}

data = {
      "format": "csv",
      "timezone": "UTC"
    }

response = requests.post(
    'https://gate.ummah.com/api/v1/company_statements/',
    headers=headers,
    json=data
)

print(response.json())
Response
{
  "id": "stmt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "type": "company",
  "format": "csv",
  "status": "processing",
  "download_url": null,
  "timezone": "UTC",
  "created_on": 1700000000
}
{"error": "Bad Request", "details": {"field": ["This field is required."]}}

List Statements

GET/api/v1/company_statements/

List all generated and pending statements for your account.

Request
curl -X GET "https://gate.ummah.com/api/v1/company_statements/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/company_statements/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/company_statements/',
    headers=headers
)

print(response.json())
Response
[{
  "id": "stmt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "type": "company",
  "format": "csv",
  "status": "processing",
  "download_url": null,
  "timezone": "UTC",
  "created_on": 1700000000
}]

Retrieve a Statement

GET/api/v1/company_statements/{id}/

Retrieve a statement by its ID. Check status and download_url.

Request
curl -X GET "https://gate.ummah.com/api/v1/company_statements/{id}/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/company_statements/{id}/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/company_statements/{id}/',
    headers=headers
)

print(response.json())
Response
{
  "id": "stmt-a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "type": "company",
  "format": "csv",
  "status": "processing",
  "download_url": "https://storage.ummah.com/stmt/...",
  "timezone": "UTC",
  "created_on": 1700000000
}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Cancel Statement

POST/api/v1/company_statements/{id}/cancel/

Cancel a pending statement generation.

Request
curl -X POST "https://gate.ummah.com/api/v1/company_statements/{id}/cancel/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.post(
  'https://gate.ummah.com/api/v1/company_statements/{id}/cancel/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.post(
    'https://gate.ummah.com/api/v1/company_statements/{id}/cancel/',
    headers=headers
)

print(response.json())
Response
{"status": "cancelled"}
{"error": "Not Found", "detail": "Object with this ID does not exist."}

Get Callback Public Key

GET/api/v1/public_key/

Retrieve the public key used to verify HMAC-SHA256 signatures on callback payloads. Use this to validate that incoming callbacks genuinely come from the gateway.

Request
curl -X GET "https://gate.ummah.com/api/v1/public_key/" \
  -H "Authorization: Bearer $SECRET_KEY"
const axios = require('axios');
// import axios from 'axios'; // ES Modules

const config = {
  headers: {
    Authorization: `Bearer ${process.env.SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
};

const { data: result } = await axios.get(
  'https://gate.ummah.com/api/v1/public_key/',
  config
);

console.log(result);
import requests
import os

headers = {
    'Authorization': f'Bearer {os.environ["SECRET_KEY"]}',
}

response = requests.get(
    'https://gate.ummah.com/api/v1/public_key/',
    headers=headers
)

print(response.json())
Response
{
  "public_key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA...\n-----END PUBLIC KEY-----"
}
Reference

Common Patterns

Recipes for common integration scenarios.

One-Click Checkout

Save a card on the customer's first purchase using force_recurring: true. On subsequent orders, charge them directly server-side — no redirect, no re-entry of card details.

Step 1 — First purchase: save card
Create the initial purchase with force_recurring: true. After the customer completes checkout, the purchase object will contain a recurring_token.
Step 2 — Store the recurring token
Save purchase.recurring_token and purchase.id in your database against the customer record.
Step 3 — Charge future orders
Create a new purchase for the second order, then call POST /purchases/{id}/charge/ with the saved recurring_token. No redirect needed.
One-Click Checkout
const axios = require('axios');

const client = axios.create({
  baseURL: 'https://gate.ummah.com/api/v1',
  headers: { Authorization: `Bearer ${process.env.SECRET_KEY}` }
});

// --- First purchase: save card ---
const first = await client.post('/purchases/', {
  amount: '59.99',
  currency: 'USD',
  name: 'Order #1001',
  force_recurring: true,          // request card save
  success_redirect: 'https://yourapp.com/success',
  failure_redirect: 'https://yourapp.com/failure',
});
// Redirect customer to first.data.checkout_url
// After payment, first.data.recurring_token is available

// --- Future purchase: one-click charge ---
const newPurchase = await client.post('/purchases/', {
  amount: '79.99',
  currency: 'USD',
  name: 'Order #1002',
  skip_capture: false,
});

await client.post(`/purchases/${newPurchase.data.id}/charge/`, {
  recurring_token: savedRecurringToken, // from first purchase
});
import requests
import os

BASE = 'https://gate.ummah.com/api/v1'
headers = {'Authorization': f'Bearer {os.environ["SECRET_KEY"]}'}

# --- First purchase: save card ---
first = requests.post(f'{BASE}/purchases/', headers=headers, json={
    'amount': '59.99',
    'currency': 'USD',
    'name': 'Order #1001',
    'force_recurring': True,
    'success_redirect': 'https://yourapp.com/success',
    'failure_redirect': 'https://yourapp.com/failure',
}).json()
# Redirect customer to first['checkout_url']
# After payment, first['recurring_token'] is available

# --- Future purchase: one-click charge ---
new_purchase = requests.post(f'{BASE}/purchases/', headers=headers, json={
    'amount': '79.99',
    'currency': 'USD',
    'name': 'Order #1002',
}).json()

requests.post(
    f'{BASE}/purchases/{new_purchase["id"]}/charge/',
    headers=headers,
    json={'recurring_token': saved_recurring_token}
)

Pre-Authorization & Capture

Hold funds at booking time with skip_capture: true and only settle when you ship or provide the service. Void the hold anytime before capture if the order is cancelled.

Step 1 — Authorize (hold) funds
Create the purchase with skip_capture: true. The customer is redirected to checkout. Funds are held but not settled — no money moves yet.
Step 2 — Capture when ready to fulfil
Call POST /purchases/{id}/capture/ with the final amount (can be less than or equal to the authorized amount). Funds are now settled.
Step 3 — Void if cancelled
If the order is cancelled before capture, call POST /purchases/{id}/release/ to void the authorization. Funds are released back to the customer immediately.
Pre-Authorization & Capture
const axios = require('axios');

const client = axios.create({
  baseURL: 'https://gate.ummah.com/api/v1',
  headers: { Authorization: `Bearer ${process.env.SECRET_KEY}` }
});

// Step 1: Authorize (hold) funds
const purchase = await client.post('/purchases/', {
  amount: '150.00',
  currency: 'USD',
  name: 'Hotel Booking #882',
  skip_capture: true,             // hold — do not settle yet
  success_redirect: 'https://yourapp.com/success',
  failure_redirect: 'https://yourapp.com/failure',
});
// Redirect customer: purchase.data.checkout_url

// Step 2: Capture when ready (e.g. at check-out)
await client.post(`/purchases/${purchase.data.id}/capture/`, {
  amount: '135.00'  // may differ from authorized amount
});

// --- OR ---

// Step 3: Void if cancelled
await client.post(`/purchases/${purchase.data.id}/release/`);
import requests
import os

BASE = 'https://gate.ummah.com/api/v1'
headers = {'Authorization': f'Bearer {os.environ["SECRET_KEY"]}'}

# Step 1: Authorize (hold) funds
purchase = requests.post(f'{BASE}/purchases/', headers=headers, json={
    'amount': '150.00',
    'currency': 'USD',
    'name': 'Hotel Booking #882',
    'skip_capture': True,
    'success_redirect': 'https://yourapp.com/success',
    'failure_redirect': 'https://yourapp.com/failure',
}).json()
# Redirect customer: purchase['checkout_url']

# Step 2: Capture when ready
requests.post(
    f'{BASE}/purchases/{purchase["id"]}/capture/',
    headers=headers,
    json={'amount': '135.00'}
)

# --- OR ---

# Step 3: Void if cancelled
requests.post(f'{BASE}/purchases/{purchase["id"]}/release/', headers=headers)

Partial Refunds

Pass an amount to POST /purchases/{id}/refund/ to refund less than the full total. You can issue multiple partial refunds as long as the cumulative amount does not exceed the original captured amount.

Subscription with Trial Period

Create a billing template, subscribe the customer, then pause billing during the trial. Resume when the trial ends.

Step 1 — Create a billing template
Define the recurring plan with POST /billing_templates/ including amount, currency, and billing period.
Step 2 — Add subscriber
Call POST /billing_templates/{id}/add_subscriber/ to enrol the customer. Set status: "paused" if starting a free trial.
Step 3 — Activate after trial
When the trial period ends, call PATCH /billing_templates/{id}/clients/{client_id}/ with {"status": "active"} to start billing.

Webhook Event Simulator

Preview the exact JSON payload your server receives for each event. Copy the payload or replay it via cURL to test your webhook handler locally.

Event type
Payload
Local testing — Run ngrok http 3000 to expose your local server, then set your webhook URL in the dashboard to the ngrok tunnel. Select an event above, copy the cURL replay command, and fire it against your handler to test end-to-end without a real payment.

Error Codes

All API errors return a consistent JSON body with a machine-readable code, a human-readable message, and an optional details object for field-level validation errors.

Example Error Response
{
  "error": "card_declined",
  "message": "The card was declined by the issuing bank.",
  "details": {
    "decline_code": "insufficient_funds",
    "param": "payment_method"
  }
}

Error Code Reference

CodeHTTP StatusDescriptionRetryable?
insufficient_funds402The card or account has insufficient funds to complete the transaction.No — ask customer to use a different payment method
card_declined402The card was declined by the issuing bank. Check details.decline_code for more info.No — ask customer to contact their bank
invalid_card400Card number, expiry, or CVV is invalid or malformed.No — fix the card details and retry
expired_card402The card's expiry date has passed.No — ask customer for a new card
authentication_required4023D Secure authentication is required. Redirect the customer to the checkout URL.Yes — redirect to checkout_url
invalid_api_key401The API key is missing, malformed, or revoked.No — check your Authorization header
rate_limit_exceeded429Too many requests in a short window. Slow down and retry.Yes — retry with exponential backoff
server_error500Unexpected internal error. Our team is automatically notified.Yes — retry after a short delay

HTTP Status Summary

HTTP StatusMeaningCommon Cause
400Bad RequestMissing required field, invalid format, or validation error
401UnauthorizedMissing or invalid API key
403ForbiddenKey does not have permission for this resource
404Not FoundObject ID does not exist
409ConflictOperation not allowed in current state (e.g. refunding an unpaid purchase)
422Unprocessable EntityRequest is well-formed but semantically invalid (e.g. duplicate idempotency key with different body)
429Rate LimitedToo many requests. Back off and retry with exponential delay
500 / 503Server ErrorInternal or temporary error. Retry after a short delay

Retry Guidance

Never retry 4xx errors without changing the request
Errors like invalid_card, invalid_api_key, or 400 Bad Request indicate a problem with your request data. Retrying without fixing the issue will always fail.
Retry 429 and 5xx with exponential backoff
Wait 1s, then 2s, then 4s (up to 3 attempts). Add random jitter (±200ms) to avoid thundering herd. The Retry-After response header, when present, gives the minimum wait time.
Use idempotency keys for POST requests
Pass an Idempotency-Key: <uuid> header on all POST requests. If your request times out and you are unsure whether it succeeded, retry with the same key — the gateway will return the original response without creating a duplicate.

Full API Reference

Quick index of all 47 endpoints. Click any row to jump to the full documentation.

Payments

Subscriptions

Invoicing

Customers

Webhooks & Security

Reporting