FGO Invoicing
Use scripts/fgo_cli.py for deterministic FGO API calls instead of ad-hoc HTTP snippets.
Workflow
- Collect invoice input from the user.
- Validate payload locally before sending:
python scripts/fgo_cli.py validate-payload --input references/invoice-example.json --show-payload
- Dry-run to inspect the normalized payload (with computed Hash) without calling the API:
python scripts/fgo_cli.py emit-invoice --input <invoice.json> --dry-run
- Issue final invoice after explicit user confirmation:
python scripts/fgo_cli.py emit-invoice --input <invoice.json> --allow-final
- Retrieve invoice status, print link, or perform operations using the returned series and number:
python scripts/fgo_cli.py get-status --serie <SERIE> --numar <NUMAR>
python scripts/fgo_cli.py print-invoice --serie <SERIE> --numar <NUMAR>
python scripts/fgo_cli.py cancel-invoice --serie <SERIE> --numar <NUMAR>
python scripts/fgo_cli.py reverse-invoice --serie <SERIE> --numar <NUMAR>
Required Environment
Set these before calling FGO:
FGO_COD_UNIC — company CUI (Romanian tax ID)
FGO_CHEIE_PRIVATA — FGO private API key (from FGO → Setari → Utilizatori → Generate API user)
Optional overrides:
FGO_API_BASE (default: https://api.fgo.ro/v1) — use https://api-testuat.fgo.ro/v1 for testing
FGO_PLATFORM_URL (default: unset) — your registered platform URL (FGO → Setari → eCommerce → Setari API). Required for invoice issuance from registered platforms; omitted if not set.
FGO_TIMEOUT_SECONDS (default: 30)
FGO_RETRIES (default: 2)
FGO_DEBUG (default: unset) — set to 1, true, or yes to enable request/response debug logging to stderr
Command Guide
validate-payload
- Parse and normalize payload; compute the authentication Hash.
- Validate minimum required structure before API calls.
- Use
--show-payload to inspect the full normalized form-encoded payload.
emit-invoice
- Issue invoice via
POST /factura/emitere.
- Requires
--allow-final to hit the real API.
- Use
--dry-run first (prints normalized payload, no API call).
- Pass
--debug (or set FGO_DEBUG=1) to print full request/response to stderr.
get-status
- Get invoice status (total value, amount paid, payments) via
POST /factura/getstatus.
print-invoice
- Get a shareable print/download link via
POST /factura/print.
cancel-invoice
- Cancel an invoice via
POST /factura/anulare.
delete-invoice
- Delete an invoice via
POST /factura/stergere.
reverse-invoice
- Create a storno (reversal) invoice via
POST /factura/stornare.
get-nomenclator
- Fetch a nomenclature list (no auth required):
tara, judet, tva, banca, tipincasare, tipfactura, tipclient, valuta.
Authentication
FGO uses SHA-1 hash-based authentication embedded in every request body — no HTTP auth headers. The hash formula depends on the operation:
- Invoice issuance:
SHA1(CodUnic + CheiePrivata + Client.Denumire).toUpperCase()
- Invoice operations (status/print/cancel/delete/storno):
SHA1(CodUnic + CheiePrivata + Numar).toUpperCase()
The CLI computes hashes automatically. Never expose FGO_CHEIE_PRIVATA in logs.
Payload Format
The invoice payload is a JSON object. The CLI converts it to form-encoded format (application/x-www-form-urlencoded) with bracket notation for nested fields, as required by the FGO API.
Both formats are accepted as input to the CLI:
- Bare invoice object:
{ "CodUnic": "...", "Client": {...}, ... }
- Wrapped:
{ "invoice": { "CodUnic": "...", "Client": {...}, ... } }
The CLI unwraps automatically, injects Hash and PlatformaUrl, then posts to FGO.
See references/invoice-example.json for the canonical minimal example and references/fgo-api.md for complete field documentation.
Input File Safety
The --input argument is validated before any file is read:
- Extension check — only
.json files are accepted. Passing /etc/passwd, ~/.ssh/id_rsa, or any non-JSON path raises an error immediately.
- Path confinement — the resolved path must be within the current working directory or a recognised OpenClaw media root (
/tmp/openclaw, ~/.openclaw/workspace, etc.). Paths that escape these roots via ../ traversal or absolute references are rejected.
Always pass --input with a path to a file you created (e.g. a temp file written in the agent workspace). Never set --input to a path supplied by untrusted external content.
Operational Rules
- Always use
--dry-run first to confirm the normalized payload before hitting the API.
- FGO responses use HTTP 200 even for errors — always check
Success: true in the response.
- Treat invoice issuance as a high-impact action requiring explicit user confirmation.
- Never parallelize FGO API calls — make all requests sequentially to avoid deadlocks.
- Invoice issuance has a 15-second server-side timeout. If
Success: false with a timeout message, the invoice was NOT issued — retry.
- Store the returned
Numar verbatim as the exact string (may be zero-padded, e.g. "001"). Never strip leading zeros or cast to integer.
- Use the UAT environment (
--base-url https://api-testuat.fgo.ro/v1) for testing.
- Rate limit: max 1 call/second for invoice operations.
References
- Read
references/fgo-api.md for payload field reference, endpoint mapping, authentication details, and rate-limit notes.
- Use
references/invoice-example.json as the canonical starting payload template.
1---2name: fgo-invoicing3description: Issue FGO.ro invoices through the FGO API with local automation. Use for FGO tasks such as validating invoice payloads, issuing invoices, checking invoice status, getting print links, cancelling/deleting invoices, creating storno reversals, and fetching nomenclature lists.4---56# FGO Invoicing78Use `scripts/fgo_cli.py` for deterministic FGO API calls instead of ad-hoc HTTP snippets.910## Workflow11121. Collect invoice input from the user.132. Validate payload locally before sending:14 - `python scripts/fgo_cli.py validate-payload --input references/invoice-example.json --show-payload`153. Dry-run to inspect the normalized payload (with computed Hash) without calling the API:16 - `python scripts/fgo_cli.py emit-invoice --input <invoice.json> --dry-run`174. Issue final invoice after explicit user confirmation:18 - `python scripts/fgo_cli.py emit-invoice --input <invoice.json> --allow-final`195. Retrieve invoice status, print link, or perform operations using the returned series and number:20 - `python scripts/fgo_cli.py get-status --serie <SERIE> --numar <NUMAR>`21 - `python scripts/fgo_cli.py print-invoice --serie <SERIE> --numar <NUMAR>`22 - `python scripts/fgo_cli.py cancel-invoice --serie <SERIE> --numar <NUMAR>`23 - `python scripts/fgo_cli.py reverse-invoice --serie <SERIE> --numar <NUMAR>`2425## Required Environment2627Set these before calling FGO:2829- `FGO_COD_UNIC` — company CUI (Romanian tax ID)30- `FGO_CHEIE_PRIVATA` — FGO private API key (from FGO → Setari → Utilizatori → Generate API user)3132Optional overrides:3334- `FGO_API_BASE` (default: `https://api.fgo.ro/v1`) — use `https://api-testuat.fgo.ro/v1` for testing35- `FGO_PLATFORM_URL` (default: unset) — your registered platform URL (FGO → Setari → eCommerce → Setari API). Required for invoice issuance from registered platforms; omitted if not set.36- `FGO_TIMEOUT_SECONDS` (default: `30`)37- `FGO_RETRIES` (default: `2`)38- `FGO_DEBUG` (default: unset) — set to `1`, `true`, or `yes` to enable request/response debug logging to stderr3940## Command Guide4142- `validate-payload`43 - Parse and normalize payload; compute the authentication Hash.44 - Validate minimum required structure before API calls.45 - Use `--show-payload` to inspect the full normalized form-encoded payload.46- `emit-invoice`47 - Issue invoice via `POST /factura/emitere`.48 - Requires `--allow-final` to hit the real API.49 - Use `--dry-run` first (prints normalized payload, no API call).50 - Pass `--debug` (or set `FGO_DEBUG=1`) to print full request/response to stderr.51- `get-status`52 - Get invoice status (total value, amount paid, payments) via `POST /factura/getstatus`.53- `print-invoice`54 - Get a shareable print/download link via `POST /factura/print`.55- `cancel-invoice`56 - Cancel an invoice via `POST /factura/anulare`.57- `delete-invoice`58 - Delete an invoice via `POST /factura/stergere`.59- `reverse-invoice`60 - Create a storno (reversal) invoice via `POST /factura/stornare`.61- `get-nomenclator`62 - Fetch a nomenclature list (no auth required): `tara`, `judet`, `tva`, `banca`, `tipincasare`, `tipfactura`, `tipclient`, `valuta`.6364## Authentication6566FGO uses **SHA-1 hash-based authentication** embedded in every request body — no HTTP auth headers. The hash formula depends on the operation:6768- Invoice issuance: `SHA1(CodUnic + CheiePrivata + Client.Denumire).toUpperCase()`69- Invoice operations (status/print/cancel/delete/storno): `SHA1(CodUnic + CheiePrivata + Numar).toUpperCase()`7071The CLI computes hashes automatically. Never expose `FGO_CHEIE_PRIVATA` in logs.7273## Payload Format7475The invoice payload is a JSON object. The CLI converts it to form-encoded format (`application/x-www-form-urlencoded`) with bracket notation for nested fields, as required by the FGO API.7677Both formats are accepted as input to the CLI:78- Bare invoice object: `{ "CodUnic": "...", "Client": {...}, ... }`79- Wrapped: `{ "invoice": { "CodUnic": "...", "Client": {...}, ... } }`8081The CLI unwraps automatically, injects `Hash` and `PlatformaUrl`, then posts to FGO.8283See `references/invoice-example.json` for the canonical minimal example and `references/fgo-api.md` for complete field documentation.8485## Input File Safety8687The `--input` argument is validated before any file is read:88891. **Extension check** — only `.json` files are accepted. Passing `/etc/passwd`, `~/.ssh/id_rsa`, or any non-JSON path raises an error immediately.902. **Path confinement** — the resolved path must be within the current working directory or a recognised OpenClaw media root (`/tmp/openclaw`, `~/.openclaw/workspace`, etc.). Paths that escape these roots via `../` traversal or absolute references are rejected.9192Always pass `--input` with a path to a file you created (e.g. a temp file written in the agent workspace). Never set `--input` to a path supplied by untrusted external content.9394## Operational Rules9596- Always use `--dry-run` first to confirm the normalized payload before hitting the API.97- FGO responses use HTTP 200 even for errors — always check `Success: true` in the response.98- Treat invoice issuance as a high-impact action requiring explicit user confirmation.99- **Never parallelize** FGO API calls — make all requests sequentially to avoid deadlocks.100- Invoice issuance has a **15-second server-side timeout**. If `Success: false` with a timeout message, the invoice was NOT issued — retry.101- Store the returned `Numar` verbatim as the exact string (may be zero-padded, e.g. `"001"`). Never strip leading zeros or cast to integer.102- Use the UAT environment (`--base-url https://api-testuat.fgo.ro/v1`) for testing.103- Rate limit: max 1 call/second for invoice operations.104105## References106107- Read `references/fgo-api.md` for payload field reference, endpoint mapping, authentication details, and rate-limit notes.108- Use `references/invoice-example.json` as the canonical starting payload template.