Mark Missing Payments
Flag a tenant as having unpaid invoices. The dashboard block engages automatically two weeks after the flag is set.
The endpoint is idempotent: calling it on an already-flagged tenant returns 200 with the existing timestamp. The timestamp is never refreshed, and the unpaid-invoices notification is never re-dispatched. The Stripe-customer check only applies on fresh marks, so a tenant flagged earlier whose Stripe customer is later removed still returns the cached 200 on retry.
If a force-refresh of the timestamp and a re-notification are needed, coordinate with engineering. The Internal API does not expose that.
Endpoint
POST /internal-api/v1/tenants/{tenant}/missing-payments
Required ability
tenants:write
Path parameter
| Parameter | Type | Description |
|---|---|---|
tenant | integer | The customer tenant id. The platform tenant (1) is rejected with 403. |
Body
Empty.
What this does
- Verifies the tenant has a Stripe customer attached. Refuses with
400 (
tenant_has_no_stripe_customer) otherwise. - Writes the current timestamp to the tenant's
sign_up_intents.has_unpaid_invoices_atcolumn. - Dispatches the unpaid-invoices notification once, the first time the tenant is flagged.
The dashboard block (the customer-visible "your store is paused" page) does not engage until two weeks after the timestamp. The 2-week grace window is fixed by the platform.
Response
Success (200 OK)
Fresh mark:
{
"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"
}
}
Idempotent re-mark (returns the existing timestamp, nothing is refreshed):
{
"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"
}
}
Mark older than two weeks (block engaged):
{
"data": {
"tenant_id": "2",
"has_unpaid_invoices_at": "2026-04-01T12:00:00.000000Z",
"dashboard_blocked": true,
"missing_payment_limit_date": "2026-04-15T12:00:00.000000Z"
}
}
| Field | Type | Description |
|---|---|---|
tenant_id | string | Tenant id |
has_unpaid_invoices_at | datetime | The moment the tenant was flagged. Idempotent calls return the existing value. |
dashboard_blocked | bool | Whether the dashboard block is engaged right now (computed from current time) |
missing_payment_limit_date | datetime | has_unpaid_invoices_at + 2 weeks. The dashboard block engages once now() passes this. |
Examples
Mark a customer tenant
curl -X POST "https://app.publica.la/internal-api/v1/tenants/2/missing-payments" \
-H "Authorization: Bearer <id>|pla_int_<secret>" \
-H "Accept: application/json"
Mark already-marked (no-op)
The same call against an already-marked tenant returns 200 with the existing timestamp. Safe to retry.
curl -X POST "https://app.publica.la/internal-api/v1/tenants/2/missing-payments" \
-H "Authorization: Bearer <id>|pla_int_<secret>" \
-H "Accept: application/json"
Error Handling
400 Tenant has no Stripe customer
{
"error": {
"code": "tenant_has_no_stripe_customer",
"message": "Tenant has no stripe customer."
}
}
The tenant has no Stripe customer attached. The same code covers tenants that have never had a payment-intent record created.
401 Unauthenticated
Missing Bearer, only X-User-Token sent, or revoked token.
403 Missing ability
The token does not carry tenants:write.
{
"message": "Invalid ability provided."
}
403 Root tenant
{
"message": "Operations on the root tenant are not allowed via internal-api."
}
The path resolved to the platform tenant. Use a customer tenant id.
404 Tenant not found
{
"message": "Not found"
}
{tenant} does not resolve to any tenant. Also returned when the
request resolves to a non-platform host, or when
X-Farfalla-Tenant-Id is set to a non-platform tenant id on
app.publica.la.
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.
See also
- Clear Missing Payments -
DELETEto reverse the flag - Tenants Overview - resource overview, route shapes
- Internal API v1 Overview - auth, abilities, errors