API Reference
API Reference
GitHub ↗
Admin Panel

Plans & Quotas

Configure plans with sending limits and resource quotas

A plan is a named set of limits attached to a project. Administrators create plans and assign them, and the sending path enforces them on every message.

Plans attach to projects, not to accounts

There is no per-user plan. A person’s limits are whatever the project they are sending from carries, which is what makes one account able to sit in a generous project and a restricted one at the same time.

A value of 0 means unlimited for every limit below.

Plan Fields

FieldDefaultWhat it caps
name—Required, unique
description—Free text
is_defaultfalseThe plan used by any project with none assigned
hourly_email_limit0Emails accepted per rolling hour
daily_email_limit0Emails accepted per rolling day
max_api_keys0API keys per project
max_smtp_servers0SMTP servers per project
max_domains0Domains per project, pending ones included
max_subscribers0Subscribers per project
max_template_asset_bytes0Builder image storage per project, in bytes summed over its images

The two send limits are checked when a message is accepted and refused with HTTP 429 (or 452 over SMTP submission). The resource caps are checked at create time, so you find out when adding the key or the domain, not later. The image cap is in bytes rather than images, because one image is 2 KB and another is 10 MB and what the cap protects is storage: an upload that would cross it is refused with 429, and uploading bytes the project already holds costs nothing, since they are stored once. Resource counts come from the primary tables rather than from counters, so nothing can drift out of step with reality. A domain counts from the moment it is added, not from verification, so a cap cannot be stepped around by adding names and never verifying them.

Both kinds of limit hold under concurrent requests: a project’s count and the write it allows are serialized, so twenty sends arriving together against room for seven accept exactly seven.

Creating a Plan

POST /api/v1/admin/plans
{
    "name": "Pro",
    "description": "For growing teams",
    "hourly_email_limit": 1000,
    "daily_email_limit": 10000,
    "max_api_keys": 20,
    "max_domains": 10,
    "max_smtp_servers": 5,
    "max_subscribers": 50000,
    "max_template_asset_bytes": 104857600
}

Listing Plans

GET /api/v1/admin/plans

Returns {"plans": [...]}. There is no fetch-one route - the list is short and the console renders from it.

Updating a Plan

PATCH /api/v1/admin/plans/{id}

Takes the same fields as create, all optional: a field left out keeps what the plan has, so {"hourly_email_limit": 500} changes that limit and nothing else. A limit sent as 0 means unlimited, not unchanged. Setting is_default here is how a plan becomes the default, and the previous default is unset in the same write.

Deleting a Plan

DELETE /api/v1/admin/plans/{id}

Answers 204. Projects that carried the plan are moved to no plan in the same transaction, so they fall back to the default rather than pointing at a plan that no longer exists.

Assigning a Plan to a Project

PATCH /api/v1/admin/projects/{id}/plan
{
    "plan_id": "3f2504e0-4f89-11d3-9a0c-0305e82c3301"
}

Platform admin only. An empty plan_id clears the assignment, which puts the project back on the default plan. An unknown plan id is 404 and nothing is written.

Reading Limits and Consumption

GET /api/v1/usage

Available to any project member, scoped by the usual project header. It reports the effective plan together with current consumption, which is what the console renders on the usage screen and what tells you how close a project is to its ceiling.