Developer Docs

# 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:

1. Create a workspace — sign up and complete activation.
2. Test in the sandbox — see the Sandbox & test cards guide.
3. Generate an API key from Settings → Developer → API Keys.
4. Make your first request to confirm the key works.
5. Build against staging, then mint a production key and switch base URL.

cURL

CLI

JavaScript

Ruby

Python

Go

Rust

Elixir

Crystal

PHP

```console
curl https://ma.manza.dev/api/entity \
  -H "Authorization: Bearer sk_live_..."
```

```console
manza login
manza entity get
```

```javascript
import { Manza } from "@getmanza/sdk";
const manza = new Manza({ apiKey: process.env.MANZA_API_KEY });

await manza.entity.get();
```

```ruby
require "manza"
manza = Manza.new(api_key: ENV["MANZA_API_KEY"])

manza.entity.get
```

```python
from manza import Manza
client = Manza()  # reads MANZA_API_KEY

client.entity.get()
```

```go
import manza "github.com/getmanza/manza-go"

client, _ := manza.New(manza.WithAPIKey(os.Getenv("MANZA_API_KEY")))

entity, err := client.Entity.Get(ctx)
```

```rust
let client = manza::Client::builder()
    .api_key(std::env::var("MANZA_API_KEY")?)
    .build()?;

let entity = client.entity().get()?;
```

```elixir
{:ok, client} = Manza.new(api_key: System.fetch_env!("MANZA_API_KEY"))

{:ok, entity} = Manza.Entity.get(client)
```

```crystal
require "manza"

client = Manza::Client.new # reads MANZA_API_KEY

entity = client.entity.get
```

```php
use Manza\Client;

$client = new Client(apiKey: getenv('MANZA_API_KEY'));

$entity = $client->entity->get();
```

## Generating an API key

Your browser does not support the video tag. 

Download the video

.

To generate an API key:

1. Open Settings → Developer → API Keys in the Manza dashboard.
2. Click Create API Key.
3. Name the key (e.g. “Production”, “Staging”, “My App”) and select the scopes it needs (see Scopes below).
4. 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.
5. Copy the key immediately — it is shown only once. Store it in a secrets manager.
6. 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](https://ma.manza.dev/docs/testing), 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.

> **Keep keys secret:** Never expose keys in client-side code, public repos, or logs. If a key is compromised, revoke it immediately from the dashboard.

> **Server-side only:** The API is meant to be called from your backend, not from browser JavaScript. It sends no CORS headers, so cross-origin requests are blocked.

## 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:

```json
{
  "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`.

```http
GET /api/accounts?limit=10
```

The response contains `data` (the current page), `has_more` and `next_cursor`. When `has_more` is true, pass `next_cursor` in the next request:

```http
GET /api/accounts?limit=10&cursor=PASTE_NEXT_CURSOR_HERE
```

Continue until `has_more` is false; `next_cursor` is then `null`. Send your Bearer token with every request.

```json
{
  "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`:

```json
{
  "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.