Overview
The Manza API lets you programmatically manage accounts and transfers, invoices and customers, payment links, and checkout sessions, and subscribe to signed webhooks. It follows RESTful conventions with JSON request and response bodies.
Getting started#
The path from “I want to try Manza” to first production transaction:
- Create a workspace — sign up and complete activation.
- Test in the sandbox — see the Sandbox & test cards guide.
- Generate an API key from Settings → Developer → API Keys.
- Make your first request to confirm the key works.
- Build against staging, then mint a production key and switch base URL.
curl https://ma.manza.dev/api/entity \
-H "Authorization: Bearer sk_live_..."manza login
manza entity getimport { Manza } from "@getmanza/sdk";
const manza = new Manza({ apiKey: process.env.MANZA_API_KEY });
await manza.entity.get();require "manza"
manza = Manza.new(api_key: ENV["MANZA_API_KEY"])
manza.entity.getfrom manza import Manza
client = Manza() # reads MANZA_API_KEY
client.entity.get()import manza "github.com/getmanza/manza-go"
client, _ := manza.New(manza.WithAPIKey(os.Getenv("MANZA_API_KEY")))
entity, err := client.Entity.Get(ctx)let client = manza::Client::builder()
.api_key(std::env::var("MANZA_API_KEY")?)
.build()?;
let entity = client.entity().get()?;{:ok, client} = Manza.new(api_key: System.fetch_env!("MANZA_API_KEY"))
{:ok, entity} = Manza.Entity.get(client)require "manza"
client = Manza::Client.new # reads MANZA_API_KEY
entity = client.entity.getuse Manza\Client;
$client = new Client(apiKey: getenv('MANZA_API_KEY'));
$entity = $client->entity->get();Generating an API key#
To generate an API key:
- Open Settings → Developer → API Keys in the Manza dashboard.
- Click Create API Key.
- Name the key (e.g. “Production”, “Staging”, “My App”) and select the scopes it needs (see Scopes below).
- List the IP addresses the key may be used from (see IP allowlist below). This is required for a key with transfers:authorize and optional for any other key. Then confirm with your verification code.
- Copy the key immediately — it is shown only once. Store it in a secrets manager.
- Use it in requests as
Authorization: Bearer <key>.
Environments#
Production handles real money. The sandbox has separate data, dashboards and API keys; a key from one environment does not authenticate in another. Build and test against the sandbox, then generate a production key and switch your base URL. Examples on these pages use the host you are currently viewing, with /api as the API prefix.
Authentication#
API keys authenticate requests via a Bearer token in the Authorization header. Keys use the sk_live_ prefix and are hashed with SHA-256 before storage — Manza never stores your key in plaintext.
IP allowlist#
A key can be locked to your servers' addresses. Set the list in Settings → Developer → API Keys, on the key's page: one IPv4 or IPv6 address or CIDR network per line, up to 20. A bare address means that one host (/32 or /128). A request with the key from any other address is refused with 403 ip_not_allowed, on every endpoint.
Only a legal representative or manager can set or change the list, and only in the dashboard with a verification code. The API cannot read or change it. Every change notifies the members who approve payments.
A key with transfers:authorize must have a list. Other keys may leave it empty, which allows any address. A network that covers every address (0.0.0.0/0 or ::/0) is refused: it would look like a restriction without being one, so leave the list empty instead. Use static egress addresses: a NAT gateway, a fixed proxy, or your hosting provider's published ranges.
Versioning#
The API uses date-based versioning via the Manza-Version header. If omitted, the current version is assumed. Breaking changes ship under a new version date with a migration guide; non-breaking changes (new fields, new endpoints) apply to all versions.
The original Zazu-Version header is still accepted and responses echo both. It is deprecated — pin new clients to Manza-Version.
Rate limiting#
The general limit is 120 requests per minute per API key. Transfer initiation (POST /api/payments) also has a stricter 10 requests per minute limit. Exceeding a limit returns 429 with error.type: "rate_limit_error". Back off before retrying; spread work over time rather than retrying in a tight loop.
Errors#
All errors follow a consistent envelope format:
{
"error": {
"type": "validation_error",
"message": "Customer not found",
"param": "customer_id"
}
}| Type | HTTP | Description |
|---|---|---|
invalid_request_error | 400 | Malformed JSON or missing required parameters |
invalid_version | 400 | Unsupported Manza-Version header |
authentication_error | 401 | Missing or invalid API key |
entity_inactive | 403 | Entity has not completed activation |
forbidden_error | 403 | API access or feature not enabled |
insufficient_scope | 403 | API key lacks required scope |
ip_not_allowed | 403 | API key used from an address outside its IP allowlist |
not_found_error | 404 | Resource does not exist |
conflict | 409 | Resource conflict, such as an existing credit note |
state_error | 422 | Invalid state transition |
validation_error | 422 | Invalid request parameters |
rate_limit_error | 429 | Too many requests |
api_error | 500 | Internal server error |
Pagination#
List endpoints use cursor-based pagination, ordered by ID descending. Supply limit (default 25, clamped to 1–100) and an optional cursor. Treat the cursor as opaque; an invalid cursor returns 400 invalid_request_error.
GET /api/accounts?limit=10The response contains data (the current page), has_more and next_cursor. When has_more is true, pass next_cursor in the next request:
GET /api/accounts?limit=10&cursor=PASTE_NEXT_CURSOR_HEREContinue until has_more is false; next_cursor is then null. Send your Bearer token with every request.
{
"data": [],
"has_more": false,
"next_cursor": null
}Scopes#
Choose scopes when creating an API key. Existing keys do not gain new scopes when another product is released. If a request returns 403 insufficient_scope, create a new key with the required permissions, update your integration and revoke the old key when it is no longer used.
| Scope | Permission |
|---|---|
entity:read | Retrieve your entity |
accounts:read | Read accounts and their transactions |
transfers:read | Retrieve an API-created payment |
transfers:write | Submit a payment into the dashboard approval flow |
transfers:authorize | Authorize or decline transfer authorization challenges; never on the key that created the transfer |
beneficiaries:read | Read beneficiaries and their bank accounts |
beneficiaries:write | Create beneficiaries and their bank accounts |
beneficiaries:request_trust | Ask approvers to trust payees for machine-approved transfers |
bulk_payments:read | Registered scope; no public REST bulk-payment endpoint |
bulk_payments:write | Registered scope; no public REST bulk-payment endpoint |
invoices:read | List and retrieve invoices |
invoices:write | Create, update, delete invoices and create credit notes |
invoices:send | Send, mark paid and cancel invoices |
invoices:auto_approve | Automatically approve and send API-created invoices, bypassing approval rules |
customers:read | List and retrieve customers |
customers:write | Create, update and delete customers |
payment_links:read | List and retrieve hosted payment URLs |
payment_links:write | Create and cancel hosted payment URLs, including invoice links |
checkout_sessions:read | Retrieve hosted checkout records |
checkout_sessions:write | Create hosted checkout records |
webhook_endpoints:read | List and retrieve webhook endpoints |
webhook_endpoints:write | Create, update, delete, test, enable or disable endpoints and rotate secrets |
This catalogue lists registered permissions; product availability is checked separately. invoices:auto_approve supplements invoices:write; it does not grant invoice creation by itself.
Entity#
GET /api/entity returns the entity associated with your API key. Required scope: entity:read. Use the authenticated request in Getting started above. A successful response is 200 OK:
{
"id": "01964a3b-0000-7000-8000-000000000001",
"name": "Acme Corp",
"created_at": "2026-01-15T10:30:00Z"
}id is the entity identifier, name its name, and created_at an ISO 8601 timestamp.
Feature access#
API access must be enabled for your entity, and the entity must have completed activation. Product access and key scopes are checked independently: granting a scope does not enable a product. An unavailable feature returns 403 forbidden_error; incomplete activation returns 403 entity_inactive.
| Access requirement | Applies to |
|---|---|
| API access | All API endpoints |
| Invoicing | Invoice and customer endpoints |
| Card collection | Payment-link and checkout-session endpoints |
| Transfer initiation | Payment creation and retrieval, and beneficiary and bank-account creation and lookup |
Contact support if the product you need is unavailable. Public docs follow the deployment's released products; your entity can still have additional access restrictions.