Official Python SDK for MakePay server-side integrations. Use it to create crypto payment links, donation pages, invoices, bookkeeping records, subscriptions, POS terminals, products, Simple Shop storefronts, customer portals, branded domains, and signed webhook handlers.
Public source: https://github.com/makecryptoio/makepay-python-sdk
pip install makepayuv add makepayThe SDK targets Python 3.9 or newer, has no runtime dependencies, and uses Python standard library HTTP and crypto modules.
Create a MakePay API key in MakeCrypto and keep the secret on your server only.
import os
from makepay import MakePayClient
makepay = MakePayClient(
key_id=os.environ["MAKEPAY_KEY_ID"],
key_secret=os.environ["MAKEPAY_KEY_SECRET"],
)The client sends X-MakeCrypto-Key-Id and X-MakeCrypto-Key-Secret headers to
the MakePay partner API.
response = makepay.create_payment_link(
{
"title": "Order #1042",
"description": "Checkout for order #1042",
"amount": "129.99",
"currency": "USDT",
"orderId": "order_1042",
"customerEmail": "buyer@example.com",
"returnUrl": "https://merchant.example/orders/1042",
"successUrl": "https://merchant.example/orders/1042/success",
"failureUrl": "https://merchant.example/orders/1042/pay",
"expirationTime": "12h",
}
)
print(response["paymentLink"])Read, update, and email existing links:
makepay.list_payment_links()
makepay.get_payment_link("PAYMENT_LINK_UID")
makepay.update_payment_link("PAYMENT_LINK_UID", {"status": "paused"})
makepay.send_payment_request_email("PAYMENT_LINK_UID", "buyer@example.com")Donation pages are flexible-amount payment links with a public donation slug.
donation = makepay.create_donation_link(
{
"title": "Spring campaign",
"description": "Support the 2026 spring fundraiser.",
"defaultAmountUsd": "25",
"minimumAmountUsd": "5",
"donationSlug": "spring-campaign",
}
)
print(donation["paymentLink"]["publicUrl"])
makepay.list_donation_links()
makepay.get_donation_link("DONATION_UID")
makepay.update_donation_link("DONATION_UID", {"status": "paused"})Anonymous links do not use a MakePay API key. They require an explicit settlement route because MakePay cannot read merchant wallet settings.
from makepay import create_anonymous_payment_link
response = create_anonymous_payment_link(
{
"amount": "25",
"settlement": {
"currency": "USDT",
"priorities": [
{
"chain": "ETH",
"address": "0xYourSettlementWallet",
"asset": "ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7",
}
],
},
"title": "Invoice #1042",
"webhookUrl": "https://merchant.example/webhooks/makepay",
}
)Use hosted checkout for redirects, or the embed helpers when your frontend keeps the shopper on the merchant site.
from makepay import (
build_makepay_embedded_checkout_url,
build_makepay_hosted_checkout_url,
build_makepay_iframe_html,
)
payment_uid = response["paymentLink"]["uid"]
hosted_url = build_makepay_hosted_checkout_url(payment_uid)
embed_url = build_makepay_embedded_checkout_url(
payment_uid,
parent_origin="https://merchant.example",
)
iframe_html = build_makepay_iframe_html(payment_uid)Donation pages also have URL helpers:
makepay.hosted_donation_url("spring-campaign")
makepay.embedded_donation_url(
"spring-campaign",
parent_origin="https://merchant.example",
)For static CMS pages, build_makepay_embed_button_html(payment_uid) returns a
button snippet that loads the MakePay modal script, and
build_makepay_iframe_html(payment_uid) returns an iframe snippet.
makepay.upsert_customer(
{
"email": "buyer@example.com",
"name": "Buyer Example",
"clientId": "crm_123",
}
)
makepay.create_customer_portal(
"CUSTOMER_ID",
{"returnUrl": "https://merchant.example/account"},
)
makepay.create_subscription(
{
"amountUsd": "29",
"customerEmail": "buyer@example.com",
"label": "Monthly plan",
"billingIntervalUnit": "month",
"billingIntervalCount": 1,
}
)terminal = makepay.create_pos_terminal(
{
"name": "Front counter",
"pin": "1234",
"allowedAssets": ["ETH.USDT-0xdAC17F958D2ee523a2206206994597C13D831ec7"],
"emailCollectionMode": "optional_after_deposit",
"catalogEnabled": True,
}
)
makepay.list_pos_terminals()
makepay.get_pos_terminal(str(terminal["terminal"]["uid"]))makepay.create_product(
{
"name": "Digital guide",
"productType": "digital",
"basePriceUsd": "19",
"shopSlug": "digital-guide",
"images": [{"url": "https://merchant.example/guide.png", "alt": "Guide cover"}],
"variants": [{"name": "PDF", "priceUsd": "19"}],
}
)
makepay.create_product_download(
"PRODUCT_UID",
{
"fileName": "guide.pdf",
"contentType": "application/pdf",
"url": "https://merchant.example/downloads/guide.pdf",
},
)
makepay.update_shop(
{
"slug": "merchant-shop",
"displayCurrency": "USD",
"checkoutMode": "hosted",
"branding": {"accentColor": "#14b8a6"},
}
)
makepay.update_shop_domain("shop.merchant.example")
makepay.refresh_shop_domain()
makepay.create_shop_coupon(
{
"code": "SPRING10",
"discountType": "percent",
"value": "10",
}
)
makepay.list_shop_orders({"status": "paid", "limit": 25})Bookkeeping APIs manage merchant invoices, expenses, supporting documents, OCR, and reconciliation links.
created = makepay.create_bookkeeping_invoice(
{
"title": "Invoice #1042",
"currency": "USD",
"issueDate": "2026-05-15",
"dueDate": "2026-05-30",
"counterparty": {
"name": "Buyer Example",
"email": "buyer@example.com",
"clientId": "crm_123",
},
"lineItems": [
{
"description": "Implementation services",
"quantity": "1",
"unitAmount": "500",
"taxAmount": "0",
}
],
"metadata": {"orderId": "order_1042"},
}
)
makepay.create_bookkeeping_invoice_payment_link(
"INVOICE_UID",
{"sendPaymentRequestEmail": True},
)
makepay.list_bookkeeping_invoices()
makepay.get_bookkeeping_invoice("INVOICE_UID")
makepay.update_bookkeeping_invoice("INVOICE_UID", {"status": "open"})Expenses can be created manually or from wallet activity, then linked back to payments, transfers, invoices, or uploaded receipts.
makepay.create_bookkeeping_expense(
{
"title": "Hosting",
"amount": "49",
"currency": "USD",
"incurredOn": "2026-05-15",
"category": "Infrastructure",
"counterparty": {"name": "Vendor Example", "type": "vendor"},
}
)
makepay.create_bookkeeping_expense_from_activity(
{
"walletActivityEventKey": "CHAIN_EVENT_KEY",
"category": "Settlement",
}
)
makepay.create_bookkeeping_reconciliation(
{
"invoiceId": "INVOICE_UID",
"paymentSessionId": "PAYMENT_SESSION_ID",
"linkType": "payment",
}
)Document uploads use multipart form data. Pass bytes, a file path, or a readable file object.
with open("receipt.pdf", "rb") as receipt:
makepay.upload_bookkeeping_document(
{
"file": receipt,
"fileName": "receipt.pdf",
"documentType": "receipt",
"expenseId": "EXPENSE_UID",
}
)
makepay.list_bookkeeping_documents()
makepay.get_bookkeeping_document_download_url("DOCUMENT_UID")
makepay.run_bookkeeping_document_ocr("DOCUMENT_UID")
makepay.get_bookkeeping_summary()makepay.update_branding(
{
"brandName": "Merchant",
"supportEmail": "support@merchant.example",
"brandingBrandColor": "#111827",
"brandingAccentColor": "#14b8a6",
"paymentLinkTheme": "system",
"paymentLinkDomain": "pay.merchant.example",
"emailSendingDomain": "mail.merchant.example",
}
)
makepay.refresh_branding_domains("all")makepay.get_settings()
makepay.update_settings(
{
"callbackUrl": "https://merchant.example/webhooks/makepay",
}
)
makepay.list_destination_assets()
makepay.list_webhook_requests({"limit": 25})Read the exact raw body before parsing JSON.
import os
from makepay import parse_makepay_webhook
def handle_makepay_webhook(raw_body: bytes, headers: dict[str, str]):
event = parse_makepay_webhook(
raw_body,
headers.get("x-makepay-signature"),
os.environ["MAKEPAY_WEBHOOK_SECRET"],
)
if event.get("event", {}).get("type") == "status_changed":
# Update your local order status.
pass
return "ok", 200Use verify_makepay_webhook when you only need a boolean result.
| Area | SDK methods |
|---|---|
| Payment links | create_payment_link, list_payment_links, get_payment_link, update_payment_link, send_payment_request_email |
| Donations | create_donation_link, list_donation_links, get_donation_link, update_donation_link |
| Anonymous links | create_anonymous_payment_link |
| Checkout | hosted, embedded, modal, button, iframe, and donation URL helpers |
| Customers | list_customers, upsert_customer, create_customer_portal |
| Subscriptions | list_subscriptions, create_subscription |
| POS terminals | list_pos_terminals, create_pos_terminal, get_pos_terminal, update_pos_terminal |
| Products | list_products, create_product, get_product, update_product, list_product_downloads, create_product_download |
| Simple Shop | get_shop, update_shop, get_shop_builder, update_shop_builder, get_shop_domain, update_shop_domain, refresh_shop_domain, coupons, orders |
| Bookkeeping | summary, invoice, expense, document upload/OCR, and reconciliation methods |
| Branding | get_branding, update_branding, refresh_branding_domains |
| Operations | get_settings, update_settings, list_destination_assets, list_webhook_requests |
| Webhooks | verify_makepay_webhook, parse_makepay_webhook |
Python payloads are plain dictionaries that use the MakePay API field names.
New integrations should send camelCase keys such as customerEmail,
paymentLinkDomain, and billingIntervalUnit.
Model conventions:
- Use strings for decimal money values when precision matters, for example
"129.99"instead of129.99. - Dates are ISO strings. Date-only fields, such as invoice
issueDate, should useYYYY-MM-DD. - IDs are usually public
uidvalues. Bookkeeping detail endpoints accept an internal UUID or public UID. - API methods raise
MakePayErrorfor non-2xx responses. Successful responses are decoded JSON dictionaries, so production can add fields without requiring a Python package update.
| Model | Used by | Required fields | Common optional fields |
|---|---|---|---|
| Payment link payload | create_payment_link |
amount |
title, description, currency, asset, orderId, customerEmail, clientId, returnUrl, successUrl, metadata |
| Donation link payload | create_donation_link |
none | defaultAmountUsd, minimumAmountUsd, donationSlug, payment-link display and redirect fields |
| Anonymous payment link payload | create_anonymous_payment_link |
amount, settlement.currency, settlement.priorities |
title, customerEmail, orderId, metadata, branding, webhookUrl, checkout redirect URLs |
| Customer payload | upsert_customer |
one of email, customerEmail, name, clientId |
metadata |
| Subscription payload | create_subscription |
plan amount/customer fields for your billing flow | amountUsd, customerEmail, label, billingIntervalUnit, billingIntervalCount, startAt, sendPaymentRequestEmail |
| POS terminal payload | create_pos_terminal, update_pos_terminal |
name |
pin, status, allowedAssets, emailCollectionMode, catalogEnabled, displaySettings, metadata |
| Product payload | create_product, update_product |
name |
description, sku, status, productType, basePriceUsd, shopSlug, images, variants, taxRates, metadata |
| Shop payload | update_shop |
none | slug, status, displayCurrency, checkoutMode, billingDetailsRequired, shipping fields, links, SEO, tracking, branding |
| Branding payload | update_branding |
none | brand name, support email, website URL, theme colors, paymentLinkDomain, emailSendingDomain |
| Bookkeeping invoice payload | create_bookkeeping_invoice, update_bookkeeping_invoice |
none; blank invoices are allowed as drafts | invoiceNumber, status, paymentStatus, currency, issueDate, dueDate, counterparty, lineItems, documentIds |
| Bookkeeping expense payload | create_bookkeeping_expense, create_bookkeeping_expense_from_activity, update_bookkeeping_expense |
none; amount defaults to zero if no activity is used | amount, currency, category, incurredOn, walletActivityEventId, walletActivityEventKey, counterparty, metadata |
| Bookkeeping document upload | upload_bookkeeping_document |
file |
fileName, documentType, invoiceId, expenseId |
| Bookkeeping reconciliation payload | create_bookkeeping_reconciliation |
one target and one source | target: invoiceId or expenseId; source: payment link/session, subscription cycle, or wallet activity; amount, assetSymbol |
| Dictionary payload | product downloads, shop builder, coupons, settings, customer portal | route-specific | these advanced surfaces stay open-ended while their server schemas evolve |
API calls raise MakePayError with status and response_body fields.
from makepay import MakePayError
try:
makepay.get_payment_link("PAYMENT_LINK_UID")
except MakePayError as error:
print(error.status, error.response_body)The canonical monorepo source lives in apps/plugins/python-sdk. The public
repository at https://github.com/makecryptoio/makepay-python-sdk mirrors only
the SDK files so developers can install or inspect it without the full
MakeCrypto workspace.
The package is published as makepay on PyPI. Version 0.3.0 aligns the
Python surface with the MakePay JavaScript SDK 0.3.0.