QUICKSTART
Start with the skill and a revocable token.
- Download the ttyinv-invoice skill with its SHA-256 checksum, or inspect the Agents page.
- Sign in on the hosted app, create a named token, and store it locally as
TTYINV_AGENT_TOKEN. - Choose MCP or REST. Both create the same portable
ttyinv/v1Markdown.
DISCOVERY
Fetch the live map before you call an endpoint.
Fetch https://app.ttyinv.com/api/v1 first. Then fetch https://app.ttyinv.com/api/v1/invoices/schema for exact input and output schemas.
The discovery response lists service and contract versions, REST paths, MCP tools, authentication, purchase rules, status meanings, and response headers.
curl --fail --silent --show-error "https://app.ttyinv.com/api/v1"
AUTHENTICATION
Bearer tokens are private and shown once.
Send Authorization: Bearer $TTYINV_AGENT_TOKEN on MCP and REST requests. Tokens expire, can be revoked immediately, and are stored by ttyinv only as SHA-256 digests.
- Keep tokens in an environment variable or secret manager, not source, command history, URLs, chat, screenshots, or logs.
- Never use verbose HTTP output or shell tracing around authenticated commands.
- A
401means the token is missing, expired, invalid, or revoked. Create a replacement. - A
429includes a retry boundary. Stop or wait.
1 · MCP
Prefer MCP when your agent supports tools.
Use the Streamable HTTP endpoint at https://app.ttyinv.com/mcp. Send a Bearer token on every request.
Initialize with MCP initialize over POST. Discover tools with tools/list after initialization.
{
"mcpServers": {
"ttyinv": {
"type": "http",
"url": "https://app.ttyinv.com/mcp",
"headers": { "Authorization": "Bearer $TTYINV_AGENT_TOKEN" }
}
}
}create_invoiceCreate needs no purchase. Its input and output schemas come from the live schema.validate_invoiceValidate needs no purchase. Its input and output schemas come from the live schema.render_invoiceRender needs an active lifetime purchase. Its input and output schemas come from the live schema.MCP returns JSON errors with the same status meanings as REST. Common statuses include 400, 401, 402, 403, 413, 422, 429, 503, and 504.
2 · REST API
Use strict JSON over ordinary HTTP.
Discovery and authenticated REST operations use Cache-Control: no-store. The public schema uses Cache-Control: public, max-age=300, stale-while-revalidate=3600. Fetch discovery, then fetch the schema.
| Endpoint | Authentication and content type | Input and success output | Purchase | Common failures |
|---|---|---|---|---|
GET https://app.ttyinv.com/api/v1 | None. Server: Returns application/json. | Input: none. Success: 200, discovery document. | None. | None expected. |
GET https://app.ttyinv.com/api/v1/invoices/schema | None. Server: Returns application/json. | Input: none. Success: 200, schema envelope. | None. | None expected. |
POST https://app.ttyinv.com/api/v1/invoices | Bearer token. Client: Send application/json. | Input: operations.create.input. Success: 201, operations.create.output. | None. | 400, 401, 403, 413, 415, 422, 429. |
POST https://app.ttyinv.com/api/v1/invoices/validate | Bearer token. Client: Send application/json. | Input: operations.validate.input. Success: 200, operations.validate.output. | None. | 400, 401, 403, 413, 415, 422, 429. |
POST https://app.ttyinv.com/api/v1/invoices/render | Bearer token. Client: Send application/json. | Input: operations.render.input. Success: 200, operations.render.output. | Active lifetime purchase. | 400, 401, 402, 403, 413, 415, 422, 429, 503, 504. |
SCHEMA DISCOVERY
Fetch contracts; do not copy fields into agent prompts.
https://app.ttyinv.com/api/v1/invoices/schema is the authoritative JSON Schema envelope shared by REST and MCP. Fetch it before composing requests. Do not copy field lists into prompts.
curl --fail --silent --show-error "https://app.ttyinv.com/api/v1/invoices/schema"
CREATE CONTRACT
Structured input returns source first.
This fabricated payload illustrates the shape only. Consult the live schema for required fields, limits, formats, and newly added capabilities.
{
"invoice": {
"number": "INV-EXAMPLE-001",
"title": "Fabricated services",
"issued": "2026-08-24",
"due": "2026-09-07",
"currency": "USD"
},
"from": { "name": "Northstar Example Studio", "email": "billing@example.com" },
"to": { "name": "Acme Example Client" },
"sections": [{
"title": "Services",
"table": { "headers": [{ "label": "Description" }, { "label": "Amount (USD)", "align": "right" }],
"rows": [["Fabricated accessibility review", "125.00"]] }
}]
}curl --fail-with-body --silent --show-error \ --config <(cat <<EOF header = "Authorization: Bearer $TTYINV_AGENT_TOKEN" header = "Content-Type: application/json" EOF ) --data-binary @invoice.json "https://app.ttyinv.com/api/v1/invoices" > created.json
A successful response contains source, the normalized document, a calculation summary, and warnings. Save source as the portable artifact.
SOURCE FIDELITY
Keep the authored invoice’s meaning intact.
- Payable currency: when a table has several amount columns, exactly one qualified column matching
invoice.currencyis payable. Conversions are authored explicitly; ttyinv does not fetch exchange rates. - Authored summaries: rows named
Subtotal,Total, orGrand Totalremain visible and are excluded from generated totals. - Recap tables: set
summaryOnly: truewhen a table repeats amounts from earlier sections. Its rows remain visible while the section is excluded from generated totals. - Deterministic page breaks: set
pageBreakBefore: trueon a table or prose section. The returned source emits the exact page-break marker.
Fetch https://app.ttyinv.com/api/v1/invoices/schema before composing requests so REST and MCP stay aligned.
VALIDATE CONTRACT
Validation is explicit and read-only.
jq -n --rawfile source invoice.md '{source:$source}' | \
curl --fail-with-body --silent --show-error \
--config <(cat <<EOF
header = "Authorization: Bearer $TTYINV_AGENT_TOKEN"
header = "Content-Type: application/json"
EOF
) --data-binary @- "https://app.ttyinv.com/api/v1/invoices/validate"Continue only when valid is true. Invalid responses include safe errors and warnings; revise the identified source.
RENDER CONTRACT
Render only validated source.
Input is { source, format, theme? }. Formats are html, pdf, or png; themes are light or dark.
A valid agent token and an active lifetime purchase are required for hosted rendering. Local CLI rendering remains free.
jq -n --rawfile source invoice.md '{source:$source,format:"pdf",theme:"light"}' | \
curl --fail-with-body --silent --show-error \
--config <(cat <<EOF
header = "Authorization: Bearer $TTYINV_AGENT_TOKEN"
header = "Content-Type: application/json"
EOF
) --data-binary @- "https://app.ttyinv.com/api/v1/invoices/render" > render-manifest.jsonThe output manifest reports format, pageCount, warnings, and files. PNG returns one ordered file per page; HTML and PDF return one file.
3 · CLI · LOCAL-FIRST
Use the CLI when contents must not cross the network.
Python 3.11+ and Chromium are required. Install from the source repository, then keep source and rendering on your local machine.
git clone https://github.com/kaygdotorg/ttyinv.git cd ttyinv make install ttyinv init invoice.md --with-assets ttyinv lint invoice.md --strict ttyinv render invoice.md --format both --theme light
Useful CLI commands
ttyinv init invoice.mdcreates a fabricated starter.ttyinv lint invoice.md --strictvalidates schema, tables, amounts, assets, and layout warnings.ttyinv render invoice.md --format pdf|html|bothrenders client files.ttyinv schema --output ttyinv-v1.schema.jsonwrites the document schema.
PRIVACY & DATA FLOW
Choose the boundary deliberately.
Use fabricated example.com identities for testing. Never commit a real invoice, customer record, signature, tax identifier, payment coordinate, token, or rendered artifact.