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/mcp

Interactive 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

StatusMeaning
400The body does not match the current schema. Read the command again.
401Authorize again.
402plan_required. Nothing was written. Read details.reason.
403This caller cannot do that. A demo also uses demo_business.
409The idempotency key or the record already exists. Do not mint a new key for the same intent.
429A real budget was exhausted. See below before sleeping Retry-After.
503busy. 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.