Introduction
Issue Brazilian NFS-e for MEI and Simples Nacional companies with a REST API or an AI agent (MCP): tax calculation, multiple companies and webhooks.
The Corvo API lets you register companies (MEI, Simples Nacional and other regimes), upload A1 certificates, calculate taxes before issuing, issue service invoices (NFS-e) and track their full lifecycle via webhooks. AI agents such as Claude Code, Cursor and Codex can do the same through the MCP server (see AI agents).
Quickstart
bash
export BASE_URL='https://api.corvo.tech/v1'
export CORVO_API_KEY='corvo_test_your_key'
curl "$BASE_URL/companies" -H "X-API-Key: $CORVO_API_KEY"All paths in this documentation are relative to BASE_URL (https://api.corvo.tech/v1).
Response formats
REST successes use { "data": ... } and listings add pagination. JSON dates are ISO 8601 strings; optional fields may be absent and nullable fields may be null.
| Operation | JSON format |
|---|---|
| Create, fetch or update a company | { "data": Company } |
| List companies | { "data": Company[], "pagination": {...} } |
| Delete a company | { "data": null } |
| Certificate upload / listing | { "data": Certificate } / paginated listing |
| Issue / fetch an invoice | { "data": Invoice } |
| List invoices and events | { "data": [ ... ], "pagination": {...} } |
| Download URL / email | { "data": ... } |
| Webhooks and deliveries | { "data": ... } or paginated listing |
| Plan & quotas | { "data": ... } |
Resources come directly inside data: an invoice is data, a list is data[]. Read data exactly once. PDF/XML, redirects, OAuth, MCP/JSON-RPC, health checks and 204 responses keep their own formats.
All operations
All paths below include the default prefix. Status codes represent success according to the HTTP contract matrix; errors follow the ERROR_* format described under Errors.
| Method | Path | Function | Success |
|---|---|---|---|
| POST | /v1/companies | Register a company | 201 |
| GET | /v1/companies | List companies | 200 |
| GET | /v1/companies/:id | Fetch a company | 200 |
| PATCH | /v1/companies/:id | Update a company | 200 |
| DELETE | /v1/companies/:id | Delete a company | 200 |
| POST | /v1/companies/:companyId/certificates | Upload a certificate | 201 |
| GET | /v1/companies/:companyId/certificates | List certificates | 200 |
| DELETE | /v1/companies/:companyId/certificates/:certId | Revoke a certificate | 204 |
| POST | /v1/invoices | Request issuance | 202 |
| POST | /v1/invoices/batches | Request issuance of up to 50 invoices | 202 |
| POST | /v1/invoices/calculate | Calculate taxes without issuing | 200 |
| GET | /v1/invoices | List invoices | 200 |
| GET | /v1/invoices/:id | Fetch an invoice | 200 |
| GET | /v1/invoices/:id/xml | Download XML | 200 |
| GET | /v1/invoices/:id/pdf | Download PDF | 200 |
| GET | /v1/invoices/:id/events | Fetch event history | 200 |
| POST | /v1/invoices/:id/download-url | Generate a signed URL | 200 |
| POST | /v1/invoices/:id/email | Request email delivery | 202 |
| POST | /v1/invoices/:id/cancel | Cancel an invoice | 200/202 |
| GET | /v1/webhooks | List webhook configurations | 200 |
| POST | /v1/webhooks | Register a webhook | 201 |
| DELETE | /v1/webhooks/:id | Delete a webhook | 200 |
| POST | /v1/webhooks/:id/test | Send a test event | 200 |
| GET | /v1/webhooks/deliveries | List deliveries | 200 |
| GET | /v1/webhooks/deliveries/stats | Fetch delivery statistics | 200 |
| POST | /v1/webhooks/deliveries/:id/retry | Schedule a retry | 200 |
| GET | /v1/billing/plan | Fetch plan and consumption | 200 |
| GET | /v1/billing/usage | Fetch availability and quotas | 200 |
| POST | /v1/billing/upgrade | Schedule a plan change | 200 |
| POST | /v1/billing/downgrade | Schedule a plan change | 200 |
| GET | /v1/plans | List plan prices (public) | 200 |
| GET | /v1/plans/:slug | Fetch one plan price (public) | 200 |
| GET | /v1/plans/quote | Recommend a plan for a volume (public) | 200 |
IDs in paths represent identifiers of resources returned by the API. Store them as strings; do not use a CNPJ in place of a :id.
Integration sequence
POST /v1/companies— register the company with its CNPJ, tax regime and fiscal municipality (municipalityCode); setdefaultServiceCodeto simplify invoices.- In
live, upload a valid A1 certificate (.p12) matching the CNPJ, with its password (POST /v1/companies/:companyId/certificates). The municipal registration is optional: provide it only if the city registered the company in the national registry. POST /v1/invoices— usecompanyTaxId(company CNPJ) to request issuance (theliveenvironment requires the company to be ready).- Track the lifecycle with
GET /v1/invoices/:idand webhooks — issuance is asynchronous.