Call the API directly
This page is the human walkthrough for calling Economico over HTTPS, without an MCP connector. The same procedure, written as steps an agent can follow, is direct-api.md. Status codes and recovery live in the API reference. Authentication details live in authentication.
Economico has one host, https://economi.co. REST is /v1 on that host. The
OAuth resource is https://economi.co/mcp, and the only scope is mcp. A
token from the ChatGPT resource (https://economi.co/mcp/chatgpt) cannot call
/v1.
Before you send a write
Use a demo company or another disposable sandbox. Open a demo from
the demo picker, connect it, and take its slug from
GET /v1/businesses. Do not use the slug economico. That is Economico’s own
company.
GET /v1/business with X-Economico-Business returns demo: true on a demo,
and the name ends in (demo). Record the sandbox invoice only there, or on a
slug you have decided is disposable. Keep the access token out of the shell
history you commit, out of prompts, and out of URLs.
Authorize
Discovery:
curl -sS https://economi.co/.well-known/oauth-authorization-server
curl -sS https://economi.co/.well-known/oauth-protected-resource/mcpInteractive access is the authorization-code grant with PKCE S256, scope
mcp, and resource https://economi.co/mcp. A person approves the
connection in the browser. Access tokens last one hour. Interactive refresh
tokens last seven days. Refresh them at POST /oauth/token with
grant_type=refresh_token.
An unattended client uses POST /oauth/headless/token with
grant_type=client_credentials and a private_key_jwt assertion. That
response has an access token and no refresh token. The assertion’s aud is
https://economi.co/oauth/headless/token, and its lifetime is at most 60
seconds. Signup of that client is the authentication
guide, not this one.
Send the access token as Authorization: Bearer. A missing or rejected token
is HTTP 401 with code unauthorized, a message, a hint, and a
WWW-Authenticate challenge.
Name the business
GET /v1/businesses needs the bearer and no business header. Every other
business route needs X-Economico-Business: <slug>. Vendor-catalog routes also
omit the header. GET /v1/openapi.json without the header is the connection
document. With the header, it is that business’s permitted operations.
GET /openapi.json is public and grants nothing.
A missing header on a business route is HTTP 400 validation (“Set
X-Economico-Business to the business for this request”). A slug the connection
cannot use is HTTP 403 forbidden (“Access to this business is unavailable”).
That text does not tell you whether the slug exists.
See what the token may do
Authority is membership, the application grant, and the token ceiling,
intersected on every call. Read the statements. Do not infer them from the
scope mcp.
curl -sS https://economi.co/v1/catalog/permissions \
-H "Authorization: Bearer $ECONOMICO_TOKEN" \
-H "X-Economico-Business: $ECONOMICO_BUSINESS"GET /v1/catalog lists permitted command names and descriptions.
GET /v1/catalog/commands/parties.create returns that command’s schemas,
examples, and credential. If credential is browser, an OAuth token cannot
run it. GET /v1/reports lists report kinds. Describe a command before you
send it. The live catalog wins over this page.
Read a balance sheet
This does not change the books. currency is optional. USD selects the USD
ledger. Amounts are integer strings of minor units.
curl -sS https://economi.co/v1/reports \
-H "Authorization: Bearer $ECONOMICO_TOKEN" \
-H "X-Economico-Business: $ECONOMICO_BUSINESS" \
-H "Content-Type: application/json" \
-d '{"kind":"balance_sheet","currency":"USD"}'Record one sandbox invoice
The copy-paste bodies are in direct-api.md. They follow the
published monthly-subscription recipe: store a short order form, create a
customer, create a priced right and a template, create a draft contract, accept
it, then contracts.record with phase billing. There is no invoices.send.
messages.send is a message to another Economico business, and a demo refuses
it when to is set (demo_business, HTTP 403). This walkthrough does not send
one.
Each command is POST /v1/commands with name, input, idempotency_key, and
effective_at. effective_at is UTC and ends in Z. Retry a lost response
with the same key and the same input. The second success has replayed: true.
The same key with a different command, input, or source_document_id is HTTP
409 idempotency_conflict. A domain no-op is HTTP 200 no_change and has no
receipt.
After the billing record, read the July window:
curl -sS https://economi.co/v1/reports \
-H "Authorization: Bearer $ECONOMICO_TOKEN" \
-H "X-Economico-Business: $ECONOMICO_BUSINESS" \
-H "Content-Type: application/json" \
-d '{"kind":"income_statement","currency":"USD","from":"2026-07-01","until":"2026-08-01T00:00:00Z"}'The recipe’s later recognition step is what expects revenue.total of 4900.
This walkthrough stops at the bill, so treat a 200 as success and read the
integer strings. It does not collect the payment.
When a call fails
| Status | Meaning |
|---|---|
| 400 | The body does not match the current schema. Read the command again. |
| 401 | Authorize again. |
| 402 | plan_required. Nothing was written. Read details.reason. |
| 403 | This caller cannot do that. A demo also uses demo_business. |
| 409 | The idempotency key or the record already exists. Do not mint a new key for the same intent. |
| 429 | A real budget was exhausted. See below before sleeping Retry-After. |
| 503 | busy. The call did not start. Retry the same body after Retry-After. |
Authenticated /v1 has no general per-token rate limit. Anonymous /public/
reads are 60 per minute per address. Vendor-catalog reads are 120 per minute
per principal. A demo stops accepting writes after 2000 events. Solo without a
paid agreement stops at 100 billable events in the period (plan_required,
reason solo_limit). Logo replacements are capped per UTC day. A 429
logo_churn_exceeded still gets Retry-After: 60 from the generic header, and
that wait does not reset the day.
The agent procedure has the request bodies, the header rules, and the stop conditions in one page.