List Tenants
Retrieve a cursor-paginated directory of every tenant on the platform that has an active plan.
This is a cross-tenant route (no {tenant} parameter), so it
requires the cross-tenant ability in addition to tenants:read.
Endpoint
GET /internal-api/v1/tenants
Required abilities
tenants:read AND cross-tenant
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
per_page | integer | 100 | Items per page. Integer between 1 and 500. |
cursor | string | - | Cursor token from links.next or links.prev |
per_page is validated server-side. Values outside 1..500,
non-integers, decimals, and negatives all return 422 with the
standard Laravel validator envelope. Omit the parameter to use the
default of 100.
Response
Success (200 OK)
{
"data": [
{
"id": "1",
"name": "Publica",
"subdomain": "exquisite-hurricane-fc4hpnbsvaqj.vapor-farm-b1.com",
"final_domain": "app.publica.la",
"https": true,
"lang": "en"
},
{
"id": "2",
"name": "Barcelona Digital",
"subdomain": "barcelona-wfsrt-59-ytqs.farfalla-saas-caname.publicala.com",
"final_domain": "revisbarcelona.publicala.me",
"https": true,
"lang": "es"
},
{
"id": "14",
"name": "Ciudad Nueva",
"subdomain": "ciudadnueva-qetffdw-93.app.publica.la",
"final_domain": "ciudadnueva.publicala.me",
"https": true,
"lang": "es"
}
],
"links": {
"next": "https://app.publica.la/internal-api/v1/tenants?per_page=3&cursor=eyJpZCI6MTQsIl9wb2ludHNUb05leHRJdGVtcyI6dHJ1ZX0",
"prev": null
},
"meta": {
"has_more": true
}
}
Ids are serialized as strings. The listing includes every tenant
with an active plan on the platform, including publica.la itself
as a read-only entry. Tenants without an active plan are not
returned. Mutating endpoints target customer tenants only.
Examples
Basic list
curl -X GET "https://app.publica.la/internal-api/v1/tenants" \
-H "Authorization: Bearer <id>|pla_int_<secret>" \
-H "Accept: application/json"
Paginate
# Page 1
curl -X GET "https://app.publica.la/internal-api/v1/tenants?per_page=50" \
-H "Authorization: Bearer <id>|pla_int_<secret>" \
-H "Accept: application/json"
# Response includes:
# "links": { "next": "...?per_page=50&cursor=eyJpZCI6NTAs..." }
# Page 2
curl -X GET "https://app.publica.la/internal-api/v1/tenants?per_page=50&cursor=eyJpZCI6NTAs..." \
-H "Authorization: Bearer <id>|pla_int_<secret>" \
-H "Accept: application/json"
Iterate until meta.has_more is false. Treat the cursor as opaque
and do not parse or modify it. Its format is an implementation
detail and may change without notice.
Error Handling
422 Invalid per_page
{
"message": "The per page field must be an integer.",
"errors": {
"per_page": ["The per page field must be an integer."]
}
}
per_page failed validation (out of 1..500, non-integer,
decimal, or negative).
401 Unauthenticated
{
"message": "Unauthenticated."
}
Causes: missing Bearer, only X-User-Token sent, or revoked token.
403 Missing ability
{
"message": "Invalid ability provided."
}
The token is missing tenants:read, cross-tenant, or both.
404 Wrong host
{
"message": "Not found"
}
The request resolved to a non-platform host. The Internal API only
serves the platform host (app.publica.la). Setting
X-Farfalla-Tenant-Id to a non-platform tenant id also returns 404,
because it points the resolved tenant away from the platform.
429 Rate limited
HTTP/1.1 429 Too Many Requests
Retry-After: <seconds>
{
"message": "Too Many Attempts."
}
The token has spent its 60 RPM budget for the current minute.
See also
- Tenants Overview - resource overview, route shapes, response fields
- Internal API v1 Overview - auth, abilities, errors