diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..71e9255 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,203 @@ +# GOBL for AI agents + +This file is published at https://docs.gobl.org/AGENTS.md. It is the condensed, copy-into-your-context version of https://docs.gobl.org/llms.md for agents that write, validate or convert GOBL documents. If you are editing the docs.gobl.org repository itself, see its README. + +## What GOBL is + +GOBL (Go Business Language, https://gobl.org) is an open-source format and library for business documents: invoices, credit notes, orders, deliveries, payments, parties and items. A document is JSON (YAML is accepted on input). You write the raw facts; **build** normalises the data, calculates totals and taxes from the country's **regime** and any **addons** (local formats such as VERI*FACTU, CFDI, FatturaPA, EN 16931), and validates the result with coded rules. A built document can be wrapped in an **envelope** (header with UUID and digest, plus signatures) and converted to local XML or PDF by companion libraries. Invopop (https://docs.invopop.com/llms.md) uses GOBL as its document format. + +- Docs: any page as Markdown by appending `.md`; index at https://docs.gobl.org/llms.txt. +- Public API, no auth: `https://gobl.dev/v0` (`POST /build`, `/validate`, `/correct`, `/replicate`, `/sign`, `/verify`; `GET /regimes`, `/regimes/{code}`, `/addons`, `/addons/{key}`, `/schemas`). +- MCP: hosted `https://gobl.dev/v0/mcp` or local `gobl mcp`; tools `build`, `validate`, `correct`, `replicate`, `schema`, `regime`, `regime_list`, `addon`, `addon_list`. +- CLI: `go install github.com/invopop/gobl.dev/cmd/gobl@latest` (the CLI lives in gobl.dev, not the core library; binaries at https://github.com/invopop/gobl.dev/releases). +- Go: `go get github.com/invopop/gobl`; `env := gobl.NewEnvelope(); err := env.Insert(inv)` calculates the document; call `env.Validate()` afterwards. +- Skill: `npx skills add https://docs.gobl.org` installs https://docs.gobl.org/skill.md. + +## Mental model + +1. **Document**: JSON whose `$schema` names its type, `https://gobl.org/draft-0/bill/invoice`, `.../org/party`, `.../bill/order`, `.../bill/delivery`, `.../bill/payment`, `.../bill/status`, `.../org/item`, `.../note/message`. +2. **Build**: normalise, calculate, validate. Fills `$regime`, `type`, `currency`, `uuid`, line `sum`/`total`, tax `key`/`rate`/`percent`, `totals`, and addon extension defaults. Idempotent. +3. **Envelope**: `{"$schema": "https://gobl.org/draft-0/envelope", "head": {uuid, dig, stamps, tags, meta}, "doc": , "sigs": [...]}`. The digest seals the document; signatures cover the header. +4. **Regime** (`$regime`, a country code): tax categories, rate keys with percentages by date, tags, correction types, validation rules. Page: `https://docs.gobl.org/regimes/.md`. +5. **Addon** (`$addons`, a list of keys): rules and **extensions** (`ext` code maps) for one local format. Page: `https://docs.gobl.org/addons/.md`. +6. **Tag** (`$tags`): a scenario switch defined by the regime or addon (`simplified`, `reverse-charge`, `self-billed`, ...). +7. **Keys vs codes**: keys are GOBL's own lowercase hyphenated identifiers (`standard`, `credit-note`, `credit-transfer`); codes come from the outside world and are kept as given (`VAT`, `B98602642`, `SAMPLE`). + +## Rules + +1. **Send the minimum, let build calculate.** Never write `sum`, `total`, `totals`, `currency`, `uuid` or tax `percent` (unless the regime has no rates). Hand-written `totals` are silently replaced, never checked. +2. **Numbers are strings** with meaningful precision: `"100.00"`, `"10%"`, `"21.0%"`. JSON numbers are accepted and returned as strings. +3. **Percentages need the `%` sign.** `"percent": "21"` is read as a factor and becomes `2100%` without any error. Write `"21%"`. +4. **`$schema` is mandatory**; a document without it fails with `unknown-schema`. The envelope has its own `$schema` and the document's goes inside `doc`. +5. **Set `$regime` explicitly** to the supplier's tax country. It is inferred from `supplier.tax_id.country`, but with neither present the error is `currency: missing or invalid`. `$regime` wins over the supplier's country. Regimes: `AE AR AT BE BR CA CH CO DE DK EL ES FI FR GB IE IN IT MX NL NO PL PT SA SE SG US` (`EL` is Greece; a `GR` tax identity is normalised to `EL`). Countries without a regime need explicit `currency` and tax `percent` values. +6. **Taxes are `cat` + rate key.** `{"cat": "VAT", "rate": "standard"}` → `key: standard, rate: general, percent: 21.0%` for the regime and `issue_date` (`standard` and `general` are aliases). Other rates: `reduced`, `super-reduced`, `intermediate`, `zero`. Keys without a percent: `exempt`, `reverse-charge`. Unknown keys fail (`'bogus' rate not defined for key 'standard'`). Category codes differ by regime (`VAT`, `ST`, `IVA`, `GST`, plus `IGIC`, `IRPF` in Spain); read them from the regime page. Retained taxes (for example `IRPF`) lower `totals.payable` below `totals.total_with_tax`. `tax.prices_include: "VAT"` treats prices as tax-inclusive. +7. **Keys are lowercase, codes are uppercase as given.** `"cat": "vat"` → `invalid-category: 'vat' not defined in regime`; `"rate": "Standard"` fails too. +8. **`$addons` selects a local format**; build fills the extension defaults it can (VERI*FACTU alone yields `es-verifactu-doc-type: F1` and per-tax `es-verifactu-op-class`/`es-verifactu-regime`), and reports the rest as faults naming the extension key. Never invent an extension value; copy it from the addon page, the MCP `addon` tool or `GET /v0/addons/`. Addons: `ar-arca-v4 br-nfe-v4 br-nfse-v1 co-dian-v2 de-xrechnung-v3 de-zugferd-v2 dk-oioubl-v2 es-facturae-v3 es-sii-v1 es-tbai-v1 es-verifactu-v1 eu-en16931-v2017 fi-finvoice-v3 fr-choruspro-v1 fr-ctc-flow2-v1 fr-ctc-flow6-v1 fr-ctc-flow10-v1 fr-facturx-v1 gr-mydata-v1 it-sdi-v1 it-ticket-v1 mx-cfdi-v4 pl-favat-v3 pt-saft-v1 sa-zatca-v1`. +9. **Only defined tags are allowed**: `$tags: ["bogus"]` fails with `$tags: 'bogus' undefined`. `simplified` lets you omit the customer (under VERI*FACTU the customer is otherwise required, `GOBL-ES-VERIFACTU-BILL-INVOICE-06`, and `simplified` sets doc type `F2`); `reverse-charge` adds the regime's legal note under `tax.notes`. Legacy `tax.tags` is moved to `$tags`. +10. **Dates are `YYYY-MM-DD`.** Anything else is an input error. `issue_date` defaults to today and selects the tax rates (a 2012 Spanish invoice gets 18%). +11. **`series` + `code` is the document number.** Optional at build, `code` required to sign. Tax IDs are normalised (`ESB23103039` → `B23103039`, `es-b-986.026.42` → `B98602642`) and checksum-validated (`GOBL-GB-TAX-IDENTITY-03`). Non-tax identifiers go in `identities`. +12. **Never edit an issued invoice; correct it.** `type` `credit-note` (extends), `debit-note` (adds charges) or `corrective` (replaces), with the original in `preceding`; amounts stay positive. Allowed types are on the regime page (Spain: all three; UK: `credit-note`). Use `gobl correct -i --credit built.json`, `POST /v0/correct` or the MCP `correct` tool; never build `preceding` by hand. `gobl correct --options` shows the allowed options (`type`, `series`, `issue_date`, `reason`, `copy_tax`, `stamps`, addon extensions). +13. **Envelopes are sealed.** `gobl build -e` adds `head.uuid` and `head.dig`; `gobl sign` needs a key from `gobl keygen` and a `code` on the document; `gobl verify` checks. Editing a signed or enveloped document without rebuilding fails with `GOBL-ENVELOPE-11 envelope digest does not match document contents`. +14. **`validate` is not `build`.** Validating a partial document fails; build first. +15. **Empty `lines` fail** (`GOBL-BILL-INVOICE-10`) unless the document carries discounts or charges. Line and document `discounts`/`charges` take `percent` or `amount`. + +## Minimal examples + +Invoice input (Spain), builds to `payable: 1089.00`: + +```json +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "ES", + "series": "SAMPLE", + "code": "001", + "issue_date": "2026-09-03", + "supplier": { + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" } + }, + "customer": { + "name": "Sample Consumer S.L.", + "tax_id": { "country": "ES", "code": "B63272603" } + }, + "lines": [ + { + "quantity": "10", + "item": { "name": "Development services", "price": "100.00" }, + "discounts": [{ "percent": "10%" }], + "taxes": [{ "cat": "VAT", "rate": "standard" }] + } + ] +} +``` + +Same invoice for VERI*FACTU (build adds `tax.ext` and per-tax `ext` codes automatically): + +```json +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "ES", + "$addons": ["es-verifactu-v1"], + "series": "SAMPLE", + "code": "002", + "issue_date": "2026-09-03", + "supplier": { + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" } + }, + "customer": { + "name": "Sample Consumer S.L.", + "tax_id": { "country": "ES", "code": "B63272603" } + }, + "lines": [ + { + "quantity": "10", + "item": { "name": "Development services", "price": "100.00" }, + "taxes": [{ "cat": "VAT", "rate": "general" }] + } + ] +} +``` + +Simplified B2C invoice (no customer) under VERI*FACTU: + +```json +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "ES", + "$addons": ["es-verifactu-v1"], + "$tags": ["simplified"], + "series": "SIMP", + "code": "001", + "issue_date": "2026-09-03", + "supplier": { + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" } + }, + "lines": [ + { + "quantity": "1", + "item": { "name": "Coffee", "price": "2.50" }, + "taxes": [{ "cat": "VAT", "rate": "reduced" }] + } + ] +} +``` + +Party: + +```json +{ + "$schema": "https://gobl.org/draft-0/org/party", + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" }, + "addresses": [ + { "num": "42", "street": "Calle Pradillo", "locality": "Madrid", "region": "Madrid", "code": "28002", "country": "ES" } + ], + "emails": [{ "addr": "billing@example.com" }] +} +``` + +Public API request: + +```json +{ "data": { "$schema": "https://gobl.org/draft-0/bill/invoice", "...": "..." }, "envelop": false } +``` + +CLI loop: + +```bash +gobl build -i invoice.json # calculate and validate +gobl build invoice.json > built.json +gobl correct -i --credit built.json # credit note with preceding +gobl keygen && gobl sign -i built.json > signed.json +gobl verify signed.json +``` + +## Decoding errors + +- Shape: `{"key": "validation", "faults": [{"code": "GOBL-...", "paths": ["$.lines[0].taxes[0]"], "message": "..."}]}` or `{"key": "calculation", "message": "..."}` / `{"key": "input", "message": "..."}` for errors before validation. +- Fault codes are `GOBL---` for core rules (`GOBL-BILL-INVOICE-10`), `GOBL--...` for regime rules (`GOBL-GB-TAX-IDENTITY-03`), `GOBL--...` for addon rules (`GOBL-ES-VERIFACTU-BILL-INVOICE-06`). The rule text is in the Validation Rules table of the schema, regime or addon page. +- `currency: missing or invalid` → no regime could be determined: set `$regime` or give the supplier a `tax_id`, or for a country without a regime set `currency` and explicit `percent`s. +- `GOBL-TAX-COMBO-04 tax combo percent required` → you gave a `key` with no rate and no percent, or ran `validate` on an unbuilt document. +- `invalid-category: 'vat' not defined in regime` → category codes are uppercase and regime specific. +- `'x' rate not defined for key 'standard'` → unknown rate key; read the regime page. +- `$tags: 'x' undefined` → the regime or addon does not define that tag. +- `unknown-schema` → missing or wrong `$schema`. +- `parsing time "15/01/2026" as "2006-01-02"` → dates must be `YYYY-MM-DD`. +- `GOBL-ENVELOPE-11 envelope digest does not match document contents` → an enveloped or signed document was edited; rebuild, or correct instead. +- `envelope doc is not ready to be signed, check code or other key fields` → signing requires `code`. + +## Where to look + +| Question | URL pattern | +| --- | --- | +| Fields, calculated markers and validation rules of a type | `https://docs.gobl.org/draft-0//.md` (`bill/invoice`, `bill/line`, `org/party`, `tax/identity`, `tax/combo`, `pay/terms`, `pay/instructions`, `org/document_ref`) | +| Tax categories, rate keys, percentages, tags, correction types of a country | `https://docs.gobl.org/regimes/.md` | +| Extension codes and scenarios of a local format | `https://docs.gobl.org/addons/.md` | +| Shared code lists (UNTDID, ISO, CEF) | `https://docs.gobl.org/catalogues/.md` | +| Validation layering and fault codes | `https://docs.gobl.org/overview/validation.md` | +| Numbers, rounding, canonical JSON | `https://docs.gobl.org/overview/numbers.md`, `.../rounding.md`, `.../canonicalization.md` | +| CLI and signing walkthrough | `https://docs.gobl.org/quick-start/cli.md`, `.../quick-start/invoices.md` | +| REST API and MCP | `https://docs.gobl.org/api/introduction.md`, `.../api/mcp.md` | +| Delivering documents to tax authorities and networks | `https://docs.invopop.com/llms.md` | + +## Vocabulary + +| You might say | GOBL says | +| --- | --- | +| Invoice number | `series` + `code` | +| VAT number, NIF, RFC, tax ID | `tax_id` with `country` and `code` | +| Registration number, Peppol ID, GLN | an `identities` entry | +| 21% VAT | `{"cat": "VAT", "rate": "standard"}` | +| Prices include tax | `tax.prices_include: "VAT"` | +| Withholding | a second tax combo (`IRPF`), see `totals.retained_tax` | +| Refund | `type: credit-note` + `preceding`, via `correct --credit` | +| Replace a wrong invoice | `type: corrective` where the regime allows it | +| Receipt without customer | `$tags: ["simplified"]` | +| Reverse charge | `$tags: ["reverse-charge"]`, tax `key: reverse-charge` | +| Bank transfer, card, direct debit | `payment.instructions.key`: `credit-transfer`, `card`, `direct-debit` | +| Due in 30 days | `payment.terms.key: due-date` with `due_dates` | +| Country format, e-invoicing standard | `$addons` + `ext` codes | +| Hash, signature, authority seal | `head.dig`, `sigs`, `head.stamps` | +| Custom fields | `meta` | diff --git a/README.md b/README.md index 3536436..5845915 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,16 @@ Run the following command at the root of your documentation (where mint.json is) mint dev ``` +### 🤖 Agent-facing files + +Mintlify publishes every root-level Markdown file verbatim, so three files here exist for AI agents that consume the docs rather than for maintainers: + +- `llms.mdx` → `/llms`, the long-form primer (mental model, twelve rules, tooling, prompts, URL tables). Every JSON example on it must build with the current `gobl` CLI. +- `AGENTS.md` → `docs.gobl.org/AGENTS.md`, the condensed version integrators paste into their own agent instructions. +- `skill.md` → `/skill.md`, installed by `npx skills add https://docs.gobl.org`; it overrides Mintlify's auto-generated skill and follows the agentskills.io frontmatter. + +Hand-written pages carry `` cards (prose only in the children, no braces or angle brackets, pointing agents at `.md` URLs). Keep the three files consistent with each other when GOBL behaviour changes. + ### Generated Content Schema, catalogue, addon, and regime pages are produced by the internal Go diff --git a/addons/overview.mdx b/addons/overview.mdx index 586abf9..82945a5 100644 --- a/addons/overview.mdx +++ b/addons/overview.mdx @@ -20,3 +20,7 @@ Addons are sourced from multiple repositories: Each addon's page states the module that implements it. Support for addons was included in the `v0.200.0` release of [GOBL](https://github.com/invopop/gobl). + + +Read https://docs.gobl.org/addons/overview.md and https://docs.gobl.org/llms.md. For the country and use case I describe, identify which addon keys apply from the list under https://docs.gobl.org/addons/ and read each addon's page. For each one, list the extension keys it can require, where on the document they go (document, line, tax or party ext), the code values allowed and what they mean, the tags and scenarios it defines, and the validation rules most likely to fail. Then take my invoice, add the addon to $addons, build it with https://gobl.dev/v0/build or the gobl CLI, and show me which extensions build filled in automatically and which I must supply myself. + diff --git a/api/introduction.mdx b/api/introduction.mdx index 2f1a76e..bc401a1 100644 --- a/api/introduction.mdx +++ b/api/introduction.mdx @@ -56,6 +56,10 @@ curl -X POST https://gobl.dev/v0/build \ No authentication is required. The API is free to use. + +Read https://docs.gobl.org/api/introduction.md, https://docs.gobl.org/llms.md and the OpenAPI description linked from https://docs.gobl.org/llms.txt. Write a small client for https://gobl.dev/v0 in this project's language with functions for build, validate, correct, and fetching a regime and an addon definition. Every document request wraps the document in a data property; build accepts an envelop flag. Turn the error body, which has a key and a faults array with code, paths and message, into a typed error so callers can branch on fault codes. Send a descriptive User-Agent header. Add a test that builds the example invoice from https://docs.gobl.org/llms.md and asserts its payable total, and one that sends an invalid tax identity and asserts the fault code. + + ## MCP Server An [MCP (Model Context Protocol) server](/api/mcp) is also available for integrating GOBL with AI assistants like Claude. It exposes the same document operations plus tax reference data as MCP tools. diff --git a/api/mcp.mdx b/api/mcp.mdx index bb35139..715f58f 100644 --- a/api/mcp.mdx +++ b/api/mcp.mdx @@ -89,6 +89,10 @@ Add to your Cursor MCP settings (`.cursor/mcp.json`): } ``` + +Read https://docs.gobl.org/api/mcp.md and https://docs.gobl.org/llms.md. Add the GOBL MCP server to the agent configuration used in this project, preferring the hosted server at https://gobl.dev/v0/mcp and falling back to the local gobl mcp command if the CLI is installed. Then exercise it: call regime_list and tell me how many regimes exist, call regime for the country I name and summarise its tax categories and rate keys, call addon for the addon I name and list its extension keys, and finally call build with the example invoice from https://docs.gobl.org/llms.md and report the payable total. Tell me if any tool call fails and why. + + ## Tools The MCP server exposes 9 tools for working with GOBL documents and reference data. diff --git a/docs.json b/docs.json index d044bf7..bc44e62 100644 --- a/docs.json +++ b/docs.json @@ -38,6 +38,7 @@ "group": "Overview", "pages": [ "introduction", + "llms", "overview/components", "overview/tools", "overview/versions", @@ -405,5 +406,8 @@ "styling": { "codeblocks": "system" }, - "theme": "mint" + "theme": "mint", + "contextual": { + "options": ["copy", "chatgpt", "claude", "perplexity", "mcp", "cursor", "vscode"] + } } diff --git a/introduction.mdx b/introduction.mdx index d308741..07985a1 100644 --- a/introduction.mdx +++ b/introduction.mdx @@ -39,3 +39,7 @@ Building business documents internationally is even harder. While standards bodi Most standards are also just definitions of data structures, and don't define local taxes, let alone validation rules or calculations. GOBL seeks to solve this problem by providing a single and global source of truth, in code. Another common problem with current standards is that they're usually very verbose (like XML), too hard to read (like EDI), and cannot be stored in a database without transformation. GOBL aims to solve this problem with simple JSON Schemas meaning data can be stored and processed easily. + + + The rules that trip agents up, the tooling that validates for you, and prompts to copy. + diff --git a/llms.mdx b/llms.mdx new file mode 100644 index 0000000..e32f3da --- /dev/null +++ b/llms.mdx @@ -0,0 +1,385 @@ +--- +title: "Build with LLMs and agents" +sidebarTitle: "LLMs and agents" +description: "The shortest correct path for an AI agent to write valid GOBL documents: the mental model, the rules that trip agents up, the tooling that validates for you, and where to look things up." +--- + +This page is written for coding agents and for the people who direct them. GOBL is small enough to hold in your head, but a handful of its conventions are easy to get wrong when you have only seen XML invoices before. Every rule below was checked against the current GOBL release, and the surprising ones say why they are surprising. + + +**If you are an AI agent:** read this page in full, then fetch [docs.gobl.org/AGENTS.md](https://docs.gobl.org/AGENTS.md), a condensed version to keep in context. Both are plain Markdown. Every other page on this site is available as Markdown by adding `.md` to its URL, and [docs.gobl.org/llms.txt](https://docs.gobl.org/llms.txt) lists them all. If you are integrating with the Invopop platform, which uses GOBL as its document format, read [docs.invopop.com/llms.md](https://docs.invopop.com/llms.md) as well. + + +## The model in one minute + +A GOBL **document** is a JSON object whose `$schema` says what it is: an invoice, a party, an order. You write only the raw facts. **Build** normalises the data, calculates every derived value using the tax rules of the document's **regime** (a country) and any **addons** (a local format such as VERI\*FACTU or CFDI), and validates the result. The complete document can then be wrapped in an **envelope**, which adds a header with a UUID and a digest, and be signed. Conversion tools turn the envelope into whatever a tax authority or network wants. + + +```mermaid actions={false} +flowchart LR + A(Partial document
JSON or YAML) --> B(Build: normalise,
calculate, validate) + B --> C(Complete document
with totals and codes) + C --> D(Envelope: header,
digest, signatures) + D --> E(Convert or deliver:
UBL, CFDI, FatturaPA, PDF) + + style A fill:#ffffff11,stroke:#00000066 + style B fill:#ffffff11,stroke:#00000066 + style C fill:#ffffff11,stroke:#00000066 + style D fill:#ffffff11,stroke:#00000066 + style E fill:#ffffff11,stroke:#00000066 +``` + + +Nine words carry most of the meaning. + +| Word | What it is | Where it shows up | +| ---- | ---------- | ----------------- | +| **Document** | The business object. Its `$schema` names the type, for example `https://gobl.org/draft-0/bill/invoice`. | Everything you write | +| **Build** | Normalise, calculate and validate. Fills in `$regime`, `type`, `currency`, `uuid`, tax percentages, line sums and `totals`. | CLI `gobl build`, API `POST /build`, MCP `build` | +| **Envelope** | `head` (UUID, digest, stamps, tags) + `doc` + `sigs`. The unit that is signed and exchanged. | `$schema` `https://gobl.org/draft-0/envelope` | +| **Regime** | A country's tax rules: categories, rate keys and percentages by date, tags, correction types, validation. | `$regime`, pages under `/regimes/` | +| **Addon** | Rules for one local format or reporting system, layered on the regime. | `$addons`, pages under `/addons/` | +| **Extension** | A coded value an addon or regime requires, taken from an official code list. | `ext` maps on documents, lines, taxes and parties | +| **Tag** | A scenario switch that changes how a regime reads the document. | `$tags`, for example `simplified` or `reverse-charge` | +| **Key** | A lowercase, hyphenated identifier for a concept: `standard`, `credit-note`, `reverse-charge`. | `rate`, `key`, `type`, tags | +| **Code** | An identifier from the outside world, kept as given: `VAT`, `B98602642`, `SAMPLE-001`. | `cat`, `tax_id.code`, `series`, `code` | + +## Reading these docs as an agent + +- **Any page as Markdown**: append `.md`, for example [/draft-0/bill/invoice.md](https://docs.gobl.org/draft-0/bill/invoice.md). +- **Index of every page**: [/llms.txt](https://docs.gobl.org/llms.txt). +- **Condensed rules**: [/AGENTS.md](https://docs.gobl.org/AGENTS.md). Paste it into your project's own agent instructions. +- **Install the docs as a skill**: `npx skills add https://docs.gobl.org` adds [/skill.md](https://docs.gobl.org/skill.md) to agents that follow the agent skills specification. +- **MCP**: the hosted server at `https://gobl.dev/v0/mcp` or the local `gobl mcp` give an agent `build`, `validate`, `correct`, `replicate`, `schema`, `regime`, `regime_list`, `addon` and `addon_list` tools. Setup for Claude, Cursor and Claude Code is on the [MCP page](/api/mcp). + +Three kinds of generated page answer most questions, and they all have the same shape. + +| Page | URL | What to read | +| ---- | --- | ------------ | +| Schema | `/draft-0//`, for example [bill/invoice](/draft-0/bill/invoice) | **Properties** lists every field with its type. **Validation Rules** lists each rule with its code. Fields marked **calculated** are filled by build; never write them. | +| Regime | `/regimes/`, for example [es](/regimes/es) | **Tax Categories** with the rate keys and percentages you may use. **Correction Definitions** for the allowed correction types. **Scenarios** for the tags the regime recognises and what they change. | +| Addon | `/addons/`, for example [es-verifactu-v1](/addons/es-verifactu-v1) | **Extensions** with the exact code values each key accepts. **Scenarios** for what build fills in automatically. **Validation Rules** for what will fail. | + +## Tooling that validates for you + +Never hand-check a GOBL document. Build it with one of these and read the faults. + + + + ```bash + curl -s -X POST https://gobl.dev/v0/build \ + -H "Content-Type: application/json" \ + -d '{"data": {"$schema": "https://gobl.org/draft-0/bill/invoice", "...": "..."}}' + ``` + + The response mirrors the request: `{"data": }`. Add `"envelop": true` for an envelope. Errors come back as `{"key": "validation", "faults": [{"code", "paths", "message"}]}`. `GET /v0/regimes/ES` and `GET /v0/addons/es-verifactu-v1` return the same definitions the docs are generated from. No authentication, free to use, see the [API reference](/api/introduction). + + + The CLI is built from [gobl.dev](https://github.com/invopop/gobl.dev), which bundles the core library with every addon. + + ```bash + go install github.com/invopop/gobl.dev/cmd/gobl@latest + gobl build -i invoice.json # calculate, validate, print + gobl build -i -e invoice.json # the same, wrapped in an envelope + gobl build -i --set series=A invoice.yaml # YAML input, override a field + gobl correct -i --credit built.json # draft a credit note + gobl keygen && gobl sign -i built.json # sign with a local key + gobl verify signed.json # check digest and signatures + gobl validate built.json # validate a complete document only + ``` + + Prebuilt binaries are on the [releases page](https://github.com/invopop/gobl.dev/releases). The [CLI quick start](/quick-start/cli) walks through the message and signing example. + + + ```bash + claude mcp add gobl --transport http https://gobl.dev/v0/mcp + ``` + + Use `regime` and `addon` before writing a document to learn the exact rate keys, tags and extension codes a country expects, then `build` to validate. See the [MCP page](/api/mcp) for Claude Desktop and Cursor configuration and the full tool list. + + + ```go + inv := &bill.Invoice{ /* raw facts only */ } + env := gobl.NewEnvelope() + if err := env.Insert(inv); err != nil { /* calculation error */ } + if err := env.Validate(); err != nil { /* validation faults */ } + ``` + + `Insert` runs the calculation; call `env.Validate()` afterwards to get the same faults the CLI reports. The [GOBL README](https://github.com/invopop/gobl#usage) has the complete example. Import the addon modules you need, or the [gobl.dev bundle](https://github.com/invopop/gobl.dev), so their rules run. + + + [build.gobl.org](https://build.gobl.org) is a browser editor with the same build behaviour. [gobl.ruby](https://github.com/invopop/gobl.ruby) offers typed Ruby classes with build, validate and sign through the CLI. [gobl.ts](https://github.com/invopop/gobl.ts) provides TypeScript types. The [tools page](/overview/tools) lists the conversion libraries for UBL, CII, CFDI, FatturaPA, Facturae and more. + + + +## GOBL in twelve rules + +Checked against GOBL `v0.504.0` through gobl.dev `v0.500.15`. + +### 1. Send the minimum and let build do the maths + +You provide the facts, build provides everything derived. Never write `sum`, `total`, `totals`, tax `percent`, `currency` or `uuid` yourself. If you do send `totals`, they are recalculated and silently replaced, so a wrong figure will not raise an error. + + +```json What you send +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "ES", + "series": "SAMPLE", + "code": "001", + "issue_date": "2026-09-03", + "supplier": { + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" } + }, + "customer": { + "name": "Sample Consumer S.L.", + "tax_id": { "country": "ES", "code": "B63272603" } + }, + "lines": [ + { + "quantity": "10", + "item": { "name": "Development services", "price": "100.00" }, + "discounts": [{ "percent": "10%" }], + "taxes": [{ "cat": "VAT", "rate": "standard" }] + } + ] +} +``` + +```json What build returns +{ + "$schema": "https://gobl.org/draft-0/bill/invoice", + "$regime": "ES", + "type": "standard", + "series": "SAMPLE", + "code": "001", + "issue_date": "2026-09-03", + "currency": "EUR", + "supplier": { + "name": "Provider One S.L.", + "tax_id": { "country": "ES", "code": "B98602642" } + }, + "customer": { + "name": "Sample Consumer S.L.", + "tax_id": { "country": "ES", "code": "B63272603" } + }, + "lines": [ + { + "i": 1, + "quantity": "10", + "item": { "name": "Development services", "price": "100.00" }, + "sum": "1000.00", + "discounts": [{ "percent": "10%", "amount": "100.00" }], + "taxes": [ + { "cat": "VAT", "key": "standard", "rate": "general", "percent": "21.0%" } + ], + "total": "900.00" + } + ], + "totals": { + "sum": "900.00", + "total": "900.00", + "taxes": { + "categories": [ + { + "code": "VAT", + "rates": [ + { "key": "standard", "base": "900.00", "percent": "21.0%", "amount": "189.00" } + ], + "amount": "189.00" + } + ], + "sum": "189.00" + }, + "tax": "189.00", + "total_with_tax": "1089.00", + "payable": "1089.00" + } +} +``` + + +Building an already-built document returns it unchanged, so build is safe to repeat. + + +`validate` is not `build`. It checks a complete document and does not calculate anything, so running it on your partial input fails with tax and totals errors. Build first, validate the output if you need to. + + +### 2. Numbers are strings, and percentages need the sign + +Amounts and percentages are decimal strings: `"100.00"`, `"10%"`, `"21.0%"`. Trailing zeros are significant and set the precision, see [numbers](/overview/numbers) and [rounding](/overview/rounding). JSON numbers are accepted on input and come back as strings. + + +A percentage without the `%` sign is read as a factor, so `"percent": "21"` becomes **`2100%`** and build succeeds. Always write `"21%"` or `"21.0%"`. + + +### 3. `$schema` says what the document is + +Every document needs a `$schema`. The envelope has its own (`https://gobl.org/draft-0/envelope`) and carries the document's inside `doc`. A document without `$schema` is rejected as `unknown-schema`. + +| Schema | Use | +| ------ | --- | +| `bill/invoice` | Invoices, credit notes, debit notes, corrective invoices, proformas | +| `bill/order`, `bill/delivery`, `bill/payment`, `bill/status` | Orders, delivery notes, payment receipts and lifecycle events | +| `org/party`, `org/item` | A company or person, and a catalogue product, stored on their own | +| `note/message` | A minimal document, handy for testing signatures | + +All schema URLs start with `https://gobl.org/draft-0/`. The [schema index](/draft-0) lists every type, including the small ones such as `tax/combo`, `org/address` and `pay/terms` that appear inside the big ones. + +### 4. The regime decides the rules + +`$regime` is the country whose tax rules apply, normally the supplier's. Build infers it from `supplier.tax_id.country` when it is missing, but set it explicitly: if neither is present, the failure is the unhelpful `currency: missing or invalid`. When `$regime` and the supplier's country disagree, `$regime` wins. + +Regimes exist for `AE`, `AR`, `AT`, `BE`, `BR`, `CA`, `CH`, `CO`, `DE`, `DK`, `EL` (Greece), `ES`, `FI`, `FR`, `GB`, `IE`, `IN`, `IT`, `MX`, `NL`, `NO`, `PL`, `PT`, `SA`, `SE`, `SG` and `US`. Greece's tax code is `EL` while its address country is `GR`; build normalises a `GR` tax identity to `EL` for you. A supplier from a country without a regime has no defaults to fall back on, so you must set `currency` and give every tax an explicit `percent`. + +### 5. Taxes are keys, not numbers + +A line tax is a category code plus a rate key, and build resolves the percentage for the regime and the `issue_date`. The same Spanish document dated 2012 gets 18%, because that was the rate then. + +| You write | Build returns | Meaning | +| --------- | ------------- | ------- | +| `{"cat":"VAT","rate":"standard"}` | `key: standard, rate: general, percent: 21.0%` | The default rate. `standard` and `general` name the same thing | +| `{"cat":"VAT","rate":"reduced"}` | `key: standard, rate: reduced, percent: 10.0%` | A reduced rate defined by the regime | +| `{"cat":"VAT","rate":"zero"}` | `key: zero, percent: 0%` | Zero-rated | +| `{"cat":"VAT","key":"exempt"}` | `key: exempt`, no percent | Exempt; addons usually want an extension saying why | +| `{"cat":"VAT","key":"reverse-charge"}` | `key: reverse-charge`, no percent | The customer accounts for the tax | +| `{"cat":"VAT","percent":"21%"}` | `key: standard, percent: 21%` | Explicit percentage, for regimes without rates | +| `{"cat":"VAT","rate":"bogus"}` | `'bogus' rate not defined for key 'standard'` | Unknown keys fail the build | + +Category codes are regime specific: `VAT` in Europe, `ST` in the US, `IVA` in Mexico, `GST` in Singapore, and Spain also has `IGIC`, `IPSI`, `IRPF` and `IRNR`. Read them off the regime page or the MCP `regime` tool. Two behaviours worth knowing: a retained tax such as Spanish `IRPF` reduces `totals.payable` below `totals.total_with_tax`, and setting `tax.prices_include` to a category treats line prices as tax-inclusive and extracts the tax from them. + +### 6. Keys are lowercase, codes are as given + +Everything GOBL defines is a **key**: lowercase, hyphenated, such as `standard`, `credit-note`, `reverse-charge`, `credit-transfer`. Everything that comes from the outside world is a **code**, kept as it is: `VAT`, `IRPF`, `B98602642`, `SAMPLE`. Writing `"cat": "vat"` fails with `invalid-category: 'vat' not defined in regime`, and `"rate": "Standard"` fails the same way. Keys instead of numeric codes is the whole point of the format, so when you meet a code such as UNTDID `30`, look for the key (`credit-transfer`) rather than copying the number. + +### 7. Addons switch on a local format + +`$addons` lists the formats or reporting systems the document must satisfy: `["es-verifactu-v1"]` for VERI\*FACTU, `["mx-cfdi-v4"]` for CFDI, `["eu-en16931-v2017"]` for the European norm. An addon adds **extensions**, coded values under `ext` on the document, its lines, its taxes or its parties. Build fills in the defaults it can work out: the VERI\*FACTU addon alone turns a plain invoice into one carrying `es-verifactu-doc-type: F1` and per-tax `es-verifactu-op-class` and `es-verifactu-regime` codes. Anything it cannot infer comes back as a validation fault naming the extension key. + +The available addons are `ar-arca-v4`, `br-nfe-v4`, `br-nfse-v1`, `co-dian-v2`, `de-xrechnung-v3`, `de-zugferd-v2`, `dk-oioubl-v2`, `es-facturae-v3`, `es-sii-v1`, `es-tbai-v1`, `es-verifactu-v1`, `eu-en16931-v2017`, `fi-finvoice-v3`, `fr-choruspro-v1`, `fr-ctc-flow2-v1`, `fr-ctc-flow6-v1`, `fr-ctc-flow10-v1`, `fr-facturx-v1`, `gr-mydata-v1`, `it-sdi-v1`, `it-ticket-v1`, `mx-cfdi-v4`, `pl-favat-v3`, `pt-saft-v1` and `sa-zatca-v1`. Each has a page under [/addons](/addons/overview) whose **Extensions** section is the only reliable source for code values. + + +Never invent an extension value. Copy it from the addon page, the MCP `addon` tool, or `GET https://gobl.dev/v0/addons/`. + + +### 8. Tags name scenarios, and only known tags are allowed + +`$tags` switches on scenarios the regime or addon defines. `simplified` marks an invoice without customer details, `reverse-charge` the customer-accounts-for-VAT case, `self-billed` a buyer-issued invoice; regimes add their own, such as `customer-rates`, `cash-basis`, `second-hand-goods` or `travel-agency`. A tag nobody defines fails the build with `$tags: 'bogus-tag' undefined`. Scenarios can add legal notes under `tax.notes` and set extensions: under VERI\*FACTU, omitting the customer fails with `GOBL-ES-VERIFACTU-BILL-INVOICE-06 customer is required` unless you add `"$tags": ["simplified"]`, which also sets the document type to `F2`. Older examples put tags under `tax.tags`; build moves them to `$tags`. + +### 9. Dates are `YYYY-MM-DD` + +`issue_date`, due dates and periods are plain ISO dates: `"2026-09-03"`. Any other format is an input error before validation even starts. `issue_date` defaults to today, and rates are resolved for that date, so set it explicitly when you replay historical documents. + +### 10. Identities are normalised and checked + +`series` plus `code` is the document number. Both may be empty at build time, but `code` is required to sign, and most issuing systems assign it just before signing. A `tax_id` has a `country` and a `code`; build strips prefixes and punctuation, so `ESB23103039` and `es-b-986.026.42` become `B23103039` and `B98602642`, then validates format and checksum with codes such as `GOBL-GB-TAX-IDENTITY-03`. Use real, valid identities when testing. Other identifiers of a party, such as a registration number or a Peppol participant ID, go in `identities`, not `tax_id`. + +### 11. Never edit an issued invoice, correct it + +Corrections are new documents whose `type` is `credit-note` (a refund that extends the original), `debit-note` (extra charges) or `corrective` (a full replacement), with the original referenced in `preceding`. Amounts on a credit note are positive; the type carries the sign. Which types a regime accepts is on its page under **Correction Definitions**: Spain accepts all three and maps them onto its rectifying invoices, the United Kingdom accepts `credit-note` only. + +Do not assemble corrections by hand. `gobl correct -i --credit invoice.json`, `POST /v0/correct` or the MCP `correct` tool copies the lines and builds `preceding` with the original's `uuid`, `series`, `code` and `issue_date`, and adds whatever the regime or addon requires. Pass `--options` (or `"schema": true` over MCP) to see the correction options a document allows: `type`, `series`, `issue_date`, `reason`, `copy_tax`, `stamps` and, for some addons, extension codes. + +### 12. The envelope is sealed by its digest + +`gobl build -e` wraps the document in an envelope with `head.uuid`, a `head.dig` SHA-256 digest of the canonical document, and a `uuid` inside the document as well; the two UUIDs differ. `gobl sign` signs the header with an ES256 key from `gobl keygen`, and `gobl verify` checks both. Changing a single character of a signed or enveloped document without rebuilding fails with `GOBL-ENVELOPE-11 envelope digest does not match document contents`. Treat a signed envelope as read-only and correct it instead. Stamps from authorities live in `head.stamps`; free-form data goes in `meta`. + +## Your first document in five commands + + + + Save the "What you send" example from rule 1 as `invoice.json`, or write it as YAML. Leave out everything build calculates. + + + ```bash + gobl build -i invoice.json + ``` + + Compare the output with the "What build returns" block. Fix any `faults` by their `code` and `paths`, then rebuild. + + + ```bash + gobl build invoice.json > built.json + gobl correct -i --credit built.json + ``` + + The result has `type: credit-note`, the same series, and a `preceding` block naming the original. + + + ```bash + gobl keygen # once, creates ~/.gobl/id_es256.jwk + gobl sign -i built.json > signed.json + ``` + + The output is an envelope with one entry in `sigs`. Signing requires a `code` on the document. + + + ```bash + gobl verify signed.json && echo ok + ``` + + Edit a value in `signed.json` and run `verify` again to see `GOBL-ENVELOPE-11`. + + + +The [invoices quick start](/quick-start/invoices) does the same with YAML and adds a PDF preview. + +## Prompts to copy + +Each card copies a complete prompt for your coding agent. They point the agent at the Markdown sources above so it works from current documentation rather than memory. + + +Convert my invoice data into a GOBL bill/invoice document. First read https://docs.gobl.org/llms.md in full, then the schema at https://docs.gobl.org/draft-0/bill/invoice.md and the regime page for the supplier's country at https://docs.gobl.org/regimes/ followed by the lowercase country code and .md. Write the minimal document: $schema, $regime, series, issue_date in YYYY-MM-DD form, supplier and customer with tax_id objects, and lines with quantity, item name and price as strings and taxes expressed as an uppercase category code plus a lowercase rate key. Do not write sums, totals, currency, uuid or tax percentages, and if you must write a percentage include the percent sign. If I name a local format, add its key to $addons and read its page under https://docs.gobl.org/addons/ for the extension codes. Then build the document by posting it wrapped in a data property to https://gobl.dev/v0/build, or with gobl build if the CLI is installed, or with the build tool of the GOBL MCP server. If it fails, read each fault's code and paths, look the code up on the schema page, fix the document and try again. Show me the built result and explain every field you were unsure about. + + + +I need to issue invoices in the country I name. Read https://docs.gobl.org/llms.md, then the regime page at https://docs.gobl.org/regimes/ followed by the lowercase tax country code and .md, and the page of every addon whose key starts with that country code under https://docs.gobl.org/addons/. Summarise for me: the tax categories and the rate keys with their current percentages, the tags the regime defines and what each one changes, the correction types allowed, the extensions each addon requires and where their code values come from, and the validation rules most likely to fail for a first-time user. Then write one minimal invoice for that country that satisfies the regime and the most relevant addon, build it with https://gobl.dev/v0/build or the gobl CLI, and show me the built output. + + + +I have a built GOBL invoice and need to correct it. Read rule 11 in https://docs.gobl.org/llms.md and the Correction Definitions section of the regime page for the document's $regime under https://docs.gobl.org/regimes/. Tell me which correction types this regime allows and which one fits my situation: a refund or partial refund, extra charges, or replacing the original because a key detail was wrong. Then produce the corrective document with gobl correct, POST https://gobl.dev/v0/correct or the correct tool of the GOBL MCP server, using the options schema to supply any required reason or extension codes. Never assemble the preceding block by hand. Show me the built result and point out how the preceding block references the original. + + + +A GOBL build failed and I will paste the error. For each fault, use its code to find the rule: codes shaped like GOBL-BILL-INVOICE-NN are on https://docs.gobl.org/draft-0/bill/invoice.md under Validation Rules, codes containing a country code such as GOBL-ES-TAX-IDENTITY-NN are on the regime page, and codes containing an addon key such as GOBL-ES-VERIFACTU-BILL-INVOICE-NN are on the addon page under https://docs.gobl.org/addons/. Explain in plain language what each rule requires and why my document fails it, referring to the JSON paths in the fault. Then propose the smallest change to the document that satisfies every rule at once, apply it, rebuild with https://gobl.dev/v0/build or the gobl CLI, and confirm the result is clean. + + + +Add GOBL support to this project. Read https://docs.gobl.org/llms.md and https://docs.gobl.org/AGENTS.md, then add the GOBL MCP server https://gobl.dev/v0/mcp to this project's agent configuration if it supports MCP, and copy the rules from AGENTS.md into this project's own agent instructions file under a heading that says they are the GOBL rules. If this is a Go project, add github.com/invopop/gobl and show me how to build an invoice with gobl.NewEnvelope and Insert. Otherwise, write a small client for POST https://gobl.dev/v0/build that wraps a document in a data property and turns the faults array into typed errors, and install the gobl CLI from github.com/invopop/gobl.dev for local checks. Finish with a test that builds the example invoice from https://docs.gobl.org/llms.md and asserts the payable total. + + +## Where to look + +| To find out | Read | +| ----------- | ---- | +| Which fields a document has, which are calculated, and how each is validated | `https://docs.gobl.org/draft-0//.md`, for example `bill/invoice`, `org/party`, `tax/combo`, `pay/terms` | +| The tax categories, rate keys, percentages, tags and correction types of a country | `https://docs.gobl.org/regimes/.md` | +| The extension codes and scenarios of a local format | `https://docs.gobl.org/addons/.md` | +| Shared code lists such as UNTDID or ISO | `https://docs.gobl.org/catalogues/.md` | +| How validation is layered and what a fault code means | [Validation rules](/overview/validation) | +| Why amounts are strings and how rounding works | [Numbers](/overview/numbers), [Rounding](/overview/rounding) | +| How the envelope digest is computed | [Canonicalization](/overview/canonicalization), [Envelope](/draft-0/envelope) | +| Building and signing from the command line | [CLI](/quick-start/cli), [Invoices](/quick-start/invoices) | +| The REST API and MCP server | [API](/api/introduction), [MCP](/api/mcp) | +| Sending GOBL documents to tax authorities and networks | [Invopop docs for agents](https://docs.invopop.com/llms.md) | + +## Vocabulary map + +| If you are thinking | GOBL says | +| ------------------- | --------- | +| Invoice number | `series` + `code` | +| VAT number, tax ID, NIF, RFC | `tax_id` with `country` and `code` | +| Company registration number, Peppol ID, GLN | an entry in `identities` | +| 21% VAT | `{"cat": "VAT", "rate": "standard"}` resolved for regime and date | +| Tax-inclusive prices | `tax.prices_include: "VAT"` | +| Withholding, retention | a second tax combo such as `{"cat": "IRPF", "percent": "15%"}`; see `totals.retained_tax` | +| Refund, credit | `type: credit-note` with `preceding`, made with `gobl correct --credit` | +| Replace a wrong invoice | `type: corrective`, where the regime allows it | +| B2C receipt without customer details | `$tags: ["simplified"]`, customer omitted | +| Reverse charge | `$tags: ["reverse-charge"]` and tax `key: reverse-charge` | +| Country format, e-invoicing standard | an addon in `$addons` plus its `ext` codes | +| Bank transfer, card, direct debit | `payment.instructions.key`: `credit-transfer`, `card`, `direct-debit` | +| Due in 30 days | `payment.terms` with `key: due-date` and `due_dates` | +| Hash, signature, seal | `head.dig`, `sigs`, `head.stamps` on the envelope | +| Custom data | `meta` | diff --git a/overview/validation.mdx b/overview/validation.mdx index 80362b8..22751e5 100644 --- a/overview/validation.mdx +++ b/overview/validation.mdx @@ -66,6 +66,10 @@ Addon rules typically enforce the requirements of a specific standard or reporti --- + +I will paste a GOBL build error. Read https://docs.gobl.org/overview/validation.md and https://docs.gobl.org/llms.md. For each fault, find the rule by its code: core codes such as GOBL-BILL-INVOICE-NN are in the Validation Rules table of the schema page under https://docs.gobl.org/draft-0/, codes with a country such as GOBL-ES-TAX-IDENTITY-NN are on the regime page, and codes with an addon key such as GOBL-ES-VERIFACTU-BILL-INVOICE-NN are on the addon page. Explain what each rule requires and why my document fails it at the JSON paths given, propose the smallest change that satisfies all rules at once, apply it and rebuild with https://gobl.dev/v0/build or the gobl CLI to confirm. + + ## Validation codes Every assertion gets a unique code built from the package, struct, and a sequence number: diff --git a/quick-start/builder.mdx b/quick-start/builder.mdx index f9878be..a6c4d2e 100644 --- a/quick-start/builder.mdx +++ b/quick-start/builder.mdx @@ -8,3 +8,7 @@ The [GOBL Builder](https://build.gobl.org) is a fantastic starting point for lea You can checkout the [source code of the GOBL builder](https://github.com/invopop/gobl.builder) and even use this tool inside your own projects. Behind the scenes, the builder uses the GOBL compiled using the new WASM (web assembly) frameworks for Go, so there is no server-side logic, and no data leaves your browser. + + +Read https://docs.gobl.org/llms.md. Set up a way for me to build and validate GOBL documents from this project without the browser: install the gobl CLI from github.com/invopop/gobl.dev, or if I cannot install anything, write a small script that posts a document wrapped in a data property to https://gobl.dev/v0/build and prints the faults array on failure. Then take the document I give you, build it, and show me the built result next to my input so I can see what was calculated. + diff --git a/quick-start/cli.mdx b/quick-start/cli.mdx index 469da13..ad793f1 100644 --- a/quick-start/cli.mdx +++ b/quick-start/cli.mdx @@ -32,6 +32,10 @@ You should get version information back like the following, where `version` is t } ``` + +Read https://docs.gobl.org/quick-start/cli.md and https://docs.gobl.org/llms.md. Install the gobl CLI from github.com/invopop/gobl.dev with go install, or download a release binary, and confirm gobl version works. Then reproduce the quick start: write the message.json document, build it with the envelop flag, generate a key pair with gobl keygen, sign the message and verify the signed envelope. Show me each command and its output, and explain what the header uuid, the digest and the signature each guarantee. + + ### Building a Message The [notes.Message](https://github.com/invopop/gobl/blob/main/note/message.go) type is great for setting up a simple test. For this tutorial open your text editor and a simple JSON file called `message.json` that looks like: diff --git a/quick-start/invoices.mdx b/quick-start/invoices.mdx index bb2c3e1..9e32723 100644 --- a/quick-start/invoices.mdx +++ b/quick-start/invoices.mdx @@ -6,6 +6,10 @@ For this guide, we assume you already have already successfully followed in the Creating an invoice is one of the most useful features of GOBL as it demonstrates the full power of the library. For the sake of the examples on this page, we're using Spain as the base region, but everything here should be supported with minor modifications in any other supported country. + +Read https://docs.gobl.org/quick-start/invoices.md and the GOBL rules in https://docs.gobl.org/llms.md, then the regime page for my country at https://docs.gobl.org/regimes/ followed by the lowercase tax country code and .md. Rewrite the quick start invoice for a supplier and customer in my country with valid tax identities, the right tax category code and rate key, and my currency, keeping amounts as strings and dates as YYYY-MM-DD. Build it with gobl build, or by posting it wrapped in a data property to https://gobl.dev/v0/build, and show me the built document. Point out every value build added and explain where the tax percentage came from. + + ## Prepare Source To get started we're going to need some base data. Take the following yaml, modify as you see fit, and output to a file like `invoice.yaml`: diff --git a/regimes/overview.mdx b/regimes/overview.mdx index 2df3637..3bcac83 100644 --- a/regimes/overview.mdx +++ b/regimes/overview.mdx @@ -5,3 +5,7 @@ title: Overview In this section you can find autogenerated versions of the tax regime definitions built into GOBL. For the latest and most complete raw data including validation rules and algorithms, please see the [gobl github repository](https://github.com/invopop/gobl/tree/main/regimes). Your contributions to improve the quality of the data would also be greatly appreciated. + + +Read https://docs.gobl.org/llms.md and the regime page at https://docs.gobl.org/regimes/ followed by the lowercase tax country code I give you and .md. Brief me on: the tax categories and the rate keys with their current percentages and any surcharges, the tags the regime defines and what each changes, the correction types allowed, the identity formats it validates, and any extensions the regime itself requires. Then write one minimal standard invoice and one credit note for that country that build cleanly with https://gobl.dev/v0/build or the gobl CLI, and show me both built results. + diff --git a/skill.md b/skill.md new file mode 100644 index 0000000..cbcb0d9 --- /dev/null +++ b/skill.md @@ -0,0 +1,62 @@ +--- +name: gobl +description: Use when writing, validating, correcting, signing or converting GOBL (Go Business Language) documents such as invoices, credit notes, parties and orders, or when you need a country's tax categories, rate keys, tags, extension codes or correction types. Covers the build-first workflow, the rules agents most often get wrong (string amounts and the percent sign, regime inference, lowercase keys versus uppercase codes, addons and extensions, tags, dates, corrections, sealed envelopes) and where the authoritative Markdown pages are for every schema, regime and addon. +license: Apache-2.0 +metadata: + version: "2.0" + source: https://github.com/invopop/gobl.docs + canonical: https://docs.gobl.org/AGENTS.md +--- + +# GOBL + +GOBL is an open-source JSON format and Go library for business documents with the tax rules of 27 countries built in. You write only the facts of a document; `build` normalises them, calculates every derived value for the document's regime (country) and addons (local formats), and validates the result with coded rules. Built documents are wrapped in a signed envelope and converted to local formats by companion libraries. Invopop uses GOBL as its document format. + +## When to use + +- Turning application data into a `bill/invoice`, `org/party` or other GOBL document. +- Finding what a country requires: tax categories, rate keys, tags, extension codes, correction types. +- Diagnosing a build or validation error by its fault code. +- Producing a credit note or corrective invoice from an existing document. +- Building, signing or verifying envelopes from the CLI, the REST API, the MCP server or Go. + +## Read first + +1. https://docs.gobl.org/AGENTS.md - the condensed rules. Keep it in context. +2. https://docs.gobl.org/llms.md - the same rules with worked examples and prompts. +3. https://docs.gobl.org/llms.txt - the index of every page. Fetch pages as Markdown by appending `.md`. +4. For the country at hand: `https://docs.gobl.org/regimes/.md` and the relevant `https://docs.gobl.org/addons/.md`. + +## Working method + +1. Identify the supplier's tax country and any local format required. Read the regime page for rate keys, tags and correction types, and the addon page for extension codes. Or call the MCP tools `regime` and `addon`. +2. Write the minimal document: `$schema`, `$regime`, `$addons` if needed, `series`, `code` if you own numbering, `issue_date` as `YYYY-MM-DD`, `supplier` and `customer` with `tax_id`, `lines` with `quantity`, `item.name`, `item.price` as strings and `taxes` as an uppercase `cat` plus a lowercase `rate` key. No sums, totals, currency, uuid or percentages. +3. Build it: `POST https://gobl.dev/v0/build` with `{"data": }` (no auth), or `gobl build -i doc.json` (CLI from `go install github.com/invopop/gobl.dev/cmd/gobl@latest`), or the MCP `build` tool, or `gobl.NewEnvelope().Insert(doc)` in Go. +4. Read every fault by `code` and `paths`; look the code up on the schema, regime or addon page named by its prefix; fix; rebuild. +5. For corrections use `gobl correct --credit`, `POST /v0/correct` or the MCP `correct` tool. Never write `preceding` by hand. +6. To seal: `gobl build -e` for an envelope, `gobl keygen` then `gobl sign`, `gobl verify` to check. Never edit a signed envelope; correct it. + +## Rules that prevent the common failures + +- Let build calculate. Hand-written `totals` are silently replaced. +- Amounts and percentages are strings. A percentage without `%` is read as a factor: `"21"` becomes `2100%` with no error. +- Set `$regime` explicitly. Without it and without a supplier `tax_id` the error is `currency: missing or invalid`. Greece is `EL`. +- `{"cat": "VAT", "rate": "standard"}` resolves per regime and `issue_date` to `key: standard, rate: general, percent: ...`. Unknown rate keys fail. Categories are uppercase and regime specific (`VAT`, `ST`, `IVA`, `GST`, `IRPF`). +- Keys are lowercase hyphenated (`credit-note`, `reverse-charge`); codes stay as given. `"cat": "vat"` fails. +- Never invent extension codes; take them from the addon page. +- Only tags the regime or addon defines are allowed (`simplified`, `reverse-charge`, `self-billed`, ...). Omitting the customer under an addon usually needs `$tags: ["simplified"]`. +- Dates are `YYYY-MM-DD`. +- Tax IDs are normalised and checksum-validated; use real identities when testing. +- `code` is optional to build but required to sign. +- `validate` is not `build`: validating a partial document fails. +- Editing an enveloped or signed document without rebuilding fails with `GOBL-ENVELOPE-11`. + +## Reference + +- Invoice schema: https://docs.gobl.org/draft-0/bill/invoice.md +- Party schema: https://docs.gobl.org/draft-0/org/party.md +- Tax combo: https://docs.gobl.org/draft-0/tax/combo.md +- Validation rules and fault codes: https://docs.gobl.org/overview/validation.md +- Numbers and rounding: https://docs.gobl.org/overview/numbers.md, https://docs.gobl.org/overview/rounding.md +- API: https://docs.gobl.org/api/introduction.md, MCP: https://docs.gobl.org/api/mcp.md +- Sending documents to authorities and networks with Invopop: https://docs.invopop.com/llms.md diff --git a/use-cases/invoicing.mdx b/use-cases/invoicing.mdx index 80c77a5..84e4f82 100644 --- a/use-cases/invoicing.mdx +++ b/use-cases/invoicing.mdx @@ -64,6 +64,10 @@ GOBL contains tax identity code normalization and validation rules that help you One of the first tasks we do when adding a new tax regime to GOBL is figuring out the local tax code validation rules and checksum calculations with the aim of creating a central and global source reference. + +Read https://docs.gobl.org/use-cases/invoicing.md, https://docs.gobl.org/llms.md and the invoice schema at https://docs.gobl.org/draft-0/bill/invoice.md. Look at how this project represents invoices, customers, line items, taxes, discounts and payment terms, and produce a mapping table from each of our fields to the GOBL property it belongs in, naming the GOBL type for each nested object such as org/party, bill/line, tax/combo and pay/terms. Flag every field of ours that has no GOBL home and suggest whether it belongs in meta, in an identities entry or nowhere. Then write a converter function in this project's language that emits the minimal GOBL document, without totals or percentages, and a test that builds its output with https://gobl.dev/v0/build and checks the payable amount. + + ## Invoice Types GOBL defines a specific set of common [types](/draft-0/bill/invoice#type-values) assigned to an invoice via the `type` property. Other standards define many more, but these are the ones we think are key for most use cases: @@ -74,7 +78,7 @@ GOBL defines a specific set of common [types](/draft-0/bill/invoice#type-values) - `credit-note` - traditional and most frequently used type when a supplier needs to issue a refund or cancel part of an invoice through a [preceding definition](/draft-0/org/document_ref). - `debit-note` - indicates that the preceding invoice was incomplete and there are now some additional costs. Most companies will just issue a new invoice to complement the previous one as opposed to issuing a specific debit note. -Not every country will have support for all these types. Spain for example doesn't have support for credit-notes, and instead requires corrective invoices, more details below. +Not every country accepts every type, and each [tax regime](/regimes/overview) lists the ones it does under **Correction Definitions**. Spanish law, for example, recognises only rectifying invoices, so GOBL maps a `credit-note` to a rectification by differences and a `corrective` to a full replacement when converting to local formats, while the United Kingdom accepts `credit-note` only. ## Invoice Scenarios @@ -95,7 +99,7 @@ For example, to define a "simplified invoice" in Spain, essentially an invoice w In this example the validation rules for checking for the presence of the customer will be skipped. -Another common scenario deals with "reverse charge" invoices, a special VAT situation whereby the supplier is indicating that the taxes will be dealt with by the customer instead the supplier, and thus does not include any VAT. This is represented in GOBL using the `"reverse-charge"` tax tag, and will automatically include a special note. +Another common scenario deals with "reverse charge" invoices, a special VAT situation whereby the supplier is indicating that the taxes will be dealt with by the customer instead the supplier, and thus does not include any VAT. This is represented in GOBL using the `"reverse-charge"` tax tag together with a `reverse-charge` key on the line taxes, and build adds the regime's legal note under `tax.notes`. The Italian FatturaPA format for example defines some 22 different invoice type codes that cover multiple different scenarios, including self billing. To support these we've defined a set of scenarios with different tags defined in the Italian tax regime. Here's an example for an "Advance or down payment on a freelance invoice" type: