Tenants
Endpoints for reading the tenant directory and managing tenant-level state from the platform.
Route shapes
| URL | Shape |
|---|---|
/tenants | Cross-tenant |
/tenants/{tenant}/missing-payments | Tenant-scoped |
Tenant-scoped URLs name the customer tenant directly in the path.
Cross-tenant URLs span every tenant on the platform and require the
cross-tenant ability.
Path-encoded operations against the platform tenant (id 1) are
rejected with 403. An internal-api token cannot modify publica.la
through a {tenant} URL.
Endpoints
| Method | Endpoint | Required abilities | Description |
|---|---|---|---|
GET | /tenants | tenants:read, cross-tenant | List tenants with an active plan |
POST | /tenants/{tenant}/missing-payments | tenants:write | Flag a tenant as having unpaid invoices |
DELETE | /tenants/{tenant}/missing-payments | tenants:write | Clear the unpaid-invoices flag |
Tenant resource shape
The list endpoint returns a slim, read-friendly projection.
{
"id": "14",
"name": "Ciudad Nueva",
"subdomain": "ciudadnueva-qetffdw-93.app.publica.la",
"final_domain": "ciudadnueva.publicala.me",
"https": true,
"lang": "es"
}
Fields:
| Field | Type | Description |
|---|---|---|
id | string | Tenant id (serialized as a string so JavaScript clients keep precision) |
name | string | Public-facing tenant name |
subdomain | string | Internal *.app.publica.la subdomain |
final_domain | string | null | The host the tenant is reachable at end-to-end (custom domain or default), or null for tenants without a configured host |
https | bool | Tenant uses HTTPS |
lang | string | Default tenant language (ISO 639-1) |
Missing-payments resource shape
The mark and clear endpoints share a response shape:
{
"data": {
"tenant_id": "2",
"has_unpaid_invoices_at": "2026-05-05T12:21:32.000000Z",
"dashboard_blocked": false,
"missing_payment_limit_date": "2026-05-19T12:21:32.000000Z"
}
}
Fields:
| Field | Type | Description |
|---|---|---|
tenant_id | string | Tenant id |
has_unpaid_invoices_at | datetime | null | The moment the tenant was flagged as having unpaid invoices, or null |
dashboard_blocked | bool | Whether the dashboard block is currently engaged (computed from current time) |
missing_payment_limit_date | datetime | has_unpaid_invoices_at + 2 weeks. Omitted from the response when has_unpaid_invoices_at is null |
The 2-week grace period is fixed by the platform.
dashboard_blocked becomes true whenever the current time is past
missing_payment_limit_date.
Behavior on tenants without a Stripe customer
A tenant must have a Stripe customer attached for missing-payments operations to apply. The two endpoints handle the no-customer case differently:
POSTagainst a tenant without a Stripe customer returns 400 with codetenant_has_no_stripe_customer. The same code covers tenants that have never had a payment-intent record created.DELETEagainst a tenant without a Stripe customer returns 200. The implicit state is "clear", and a clear of an already-clear state is a no-op.
See also
- Internal API v1 Overview - auth, abilities, errors
- List Tenants -
GET /tenants - Mark Missing Payments -
POST /tenants/{tenant}/missing-payments - Clear Missing Payments -
DELETE /tenants/{tenant}/missing-payments