fix(docs): replace dead gnubok.app domain with app.gnubok.se across public docs (#683)

gnubok.app has no DNS delegation (the .app TLD returns no NS records for
it), so every https://gnubok.app/... link in the public docs was dead —
including the OAuth connector URL a Claude Connectors Directory reviewer
would paste from the new Connect-with-Claude page (#682), and the docs
links in the gnubok-mcp npm README that ships in the tarball.

app.gnubok.se is the live production domain (the MCP endpoint there
correctly answers 401 unauthenticated) and was already the default
GNUBOK_URL in the npm bridge and the branding-service appUrl fallback.

Mechanical swap: 55 occurrences across 11 files, all https:// URL form
(verified no emails or identifiers). Docs content only — no code paths.
Also resolves the greptile domain-mismatch finding on #682.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jakob Wennberg
2026-06-06 13:00:27 +02:00
committed by GitHub
co-authored by Claude Opus 4.8
parent a894af11d0
commit 3c85082f3a
11 changed files with 55 additions and 55 deletions
+2 -2
View File
@@ -5,7 +5,7 @@ export const CONNECT_CLAUDE_MD = `# Connect with Claude
Accounted ships an [MCP](https://modelcontextprotocol.io) server that exposes the full bookkeeping engine — 90+ tools — to any MCP client. The endpoint is:
\`\`\`
https://gnubok.app/api/extensions/ext/mcp-server/mcp
https://app.gnubok.se/api/extensions/ext/mcp-server/mcp
\`\`\`
There are two ways to connect, depending on your client. Both reach the same tools and the same approval model: read tools answer immediately, write tools (categorise, mark paid, create voucher, year-end) **stage a pending operation** that you confirm in chat or in the **/pending** web UI before anything is booked.
@@ -17,7 +17,7 @@ Best for most users. No API key to manage — you authorise Accounted the same w
1. In **claude.ai** (Settings → Connectors) or **Claude Desktop** (Settings → Connectors → Add custom connector), choose **Add custom connector**.
2. Paste the connector URL:
\`\`\`
https://gnubok.app/api/extensions/ext/mcp-server/mcp
https://app.gnubok.se/api/extensions/ext/mcp-server/mcp
\`\`\`
3. Claude opens the Accounted OAuth 2.1 consent screen. Sign in and pick the company you want Claude to act on.
4. On the consent screen you grant **read-only scopes by default** (list invoices, read reports, compute VAT). Write scopes (create invoice, categorise, book vouchers, run year-end) are **listed separately and must be ticked explicitly** — leave them unchecked for a read-only review session.
@@ -15,7 +15,7 @@ This is the operational companion to the [Reports reference](/docs/api/reference
\`GET /reports/vat-declaration\` returns rutor 05–62 plus the reconciliation block:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/vat-declaration?period=2026-04" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/vat-declaration?period=2026-04" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -88,7 +88,7 @@ The VAT declaration for April 2026 onwards will show split balances on rutor 11/
BFNAR 2013:2 kap 6–7 §§ requires every voucher gap to have a documented explanation. Skatteverket may ask why \`F-2026-0042\` exists when no \`F-2026-0041\` is on the books. Check before declaring:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/compliance/check?type=voucher_gaps&period=2026-04" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/compliance/check?type=voucher_gaps&period=2026-04" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -99,7 +99,7 @@ If gaps exist, file an explanation via \`POST /voucher-gap-explanations\` BEFORE
The declaration is computed from posted entries in the period. If the period is still open and you have draft entries that should be in this declaration, commit them before declaring. After declaring, lock the period:
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/lock" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/lock" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -113,7 +113,7 @@ v1 does not submit the declaration. The receipt-quality JSON above is what you t
For audit-trail completeness, capture the submission confirmation number from Skatteverket and store it on the period via \`PATCH /fiscal-periods/{id}\`:
\`\`\`bash
curl -X PATCH "https://gnubok.app/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID" \\
curl -X PATCH "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Content-Type: application/json" \\
-d '{ "submission_reference": "SKV-2026-04-AB123456" }'
@@ -15,7 +15,7 @@ This is the operational companion to the [Transactions reference](/docs/api/refe
\`POST /imports/bank\` accepts multipart upload. Format detection is automatic; the response includes the matched parser. The endpoint kicks off an async operation — you'll poll for the result.
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/imports/bank" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/imports/bank" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-F "file=@statement-2026-04.csv" \\
@@ -41,7 +41,7 @@ Response is a 202 with the operation handle:
Polling is the simplest pattern; subscribe to the \`operation.completed\` event ([cookbook](/docs/api/cookbook/webhooks)) for the push variant. The operation lifecycle is \`queued → running → succeeded | failed | cancelled\`.
\`\`\`bash
curl "https://gnubok.app/api/v1/operations/$OPERATION_ID" \\
curl "https://app.gnubok.se/api/v1/operations/$OPERATION_ID" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -74,7 +74,7 @@ Note the dedup: rows that match an existing transaction on \`(date, amount, desc
After ingest the rows are in \`transactions\` but uncategorised (\`account_number: null\`, \`category: null\`). List them:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/transactions?status=uncategorized&period=2026-04&limit=50" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/transactions?status=uncategorized&period=2026-04&limit=50" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -106,7 +106,7 @@ Response (cursor-paginated, oldest-first):
\`POST /transactions/{id}/suggest-categories\` returns ranked guesses based on the description, counterparty history, and your booking-template library:
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/suggest-categories" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/suggest-categories" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -140,7 +140,7 @@ Confidence ≥ 0.85 is generally safe to auto-apply; below that surface to the u
\`POST /transactions/{id}/categorize\` stages the booking. Dry-run first to see the verifikation preview:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/categorize?dry_run=true" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/categorize?dry_run=true" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -177,7 +177,7 @@ Drop \`?dry_run=true\` and reuse the same \`Idempotency-Key\` to commit. The res
For a backlog, use \`POST /transactions/batch-categorize\` (up to 100 transactions per call, dry-runnable, partial-success on commit):
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/transactions/batch-categorize" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/transactions/batch-categorize" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -209,7 +209,7 @@ Response shape — every item has its own \`ok\` flag:
When a transaction is a customer payment, match it to the open invoice via \`POST /transactions/{id}/match-invoice\` instead of \`categorize\`. The engine posts the payment voucher (debit 1930, credit 1510) AND marks the invoice paid in a single transaction.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/match-invoice" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/transactions/$TX_ID/match-invoice" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
+6 -6
View File
@@ -12,7 +12,7 @@ export const QUICKSTART_MD = `# Quickstart — send your first invoice
Test keys are scoped to a single sandbox company by default; this call confirms the auth works and returns the \`companyId\` you'll use in the rest of the cookbook.
\`\`\`bash
curl https://gnubok.app/api/v1/companies \\
curl https://app.gnubok.se/api/v1/companies \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -32,7 +32,7 @@ Save the \`id\` as \`COMPANY_ID\` for the next steps.
Every write supports \`?dry_run=true\` — the response shows the would-be record without committing. Use it in agent test loops to validate inputs before paying the side-effect cost.
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/customers?dry_run=true" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/customers?dry_run=true" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -70,7 +70,7 @@ Invoices are typed (B2B, EU-business, individual) and support mixed-rate VAT (pe
\`\`\`bash
INVOICE_IDEMP=$(uuidgen)
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/invoices" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/invoices" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $INVOICE_IDEMP" \\
-H "Content-Type: application/json" \\
@@ -106,7 +106,7 @@ Response includes the auto-allocated invoice number, the computed VAT lines, and
\`POST /invoices/{id}/send\` posts the verifikation, generates the PDF, and emails the customer in a single transaction. Strict-mode: if any step fails, none of them commit.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/send" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/send" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -125,7 +125,7 @@ Response carries the now-posted voucher number:
"request_id": "req_...",
"audit": {
"voucher_number": "F-2026-001",
"voucher_url": "https://gnubok.app/bookkeeping/...",
"voucher_url": "https://app.gnubok.se/bookkeeping/...",
"immutable_at": "2026-05-15T12:00:00Z"
}
}
@@ -137,7 +137,7 @@ Response carries the now-posted voucher number:
When the customer pays, mark the invoice paid. The engine generates the payment voucher (debit 1930 bank, credit 1510 AR) and links it to the invoice.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/mark-paid" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/mark-paid" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -15,7 +15,7 @@ This is the operational companion to the [Salary-runs reference](/docs/api/refer
\`POST /salary-runs\` opens a run in \`draft\` status. Personnummer in the response is masked to \`ÅÅÅÅMMDDXXXX\` per GDPR Art.5(1)(c) — the full value only appears on \`GET /employees/{id}\` (deliberate drill-in).
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -55,7 +55,7 @@ Totals are null until you calculate.
\`POST /salary-runs/{id}/calculate\` runs the full Swedish tax engine: skattetabell lookup per employee, sociala avgifter at the current rate (31.42% for 2026), age-adjusted reductions per Prop. 2025/26:66 (the youth-reduction band is **18–22 years old at the start of 2026** — i.e. employees **born 2003–2007** for the 2026 income year, NOT a blanket "under-25"; the elder reduction applies at **67+ from 2026**, not 66+), förmånsbeskattning, semesterlöneskuld, OB-tillägg, traktamente.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/calculate" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/calculate" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -94,7 +94,7 @@ The \`review\` status is a soft hold — the math is done but no journal entries
\`POST /salary-runs/{id}/approve\` validates and locks the math. After this point you can't \`PATCH\` per-employee \`grundlön\` etc. — corrections require reverting to draft (only possible if no payment is recorded).
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/approve" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/approve" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -112,7 +112,7 @@ Failures return \`SALARY_RUN_APPROVE_VALIDATION_FAILED\` with a per-employee bre
After the bank transfer settles (or you mark it on the same day for cash-method shops), tell Accounted:
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/mark-paid" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/mark-paid" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -132,7 +132,7 @@ This step records the payment event but does NOT post the journal entry yet —
The 2731 series is the **employer-contributions-payable** liability per BAS 2026 — not to be confused with 2615 (utgående moms vid import, unrelated to payroll). The arbetsgivardeklaration cycle posts the payable on book day and clears it via 1930 when the bank transfer to Skatteverket settles.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/book" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/book" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -166,7 +166,7 @@ If \`book\` fails partway (e.g. period locked while waiting for the bank-side co
\`POST /salary-runs/{id}/generate-agi\` produces the arbetsgivardeklaration på individnivå XML for the period. Skatteverket requires AGI monthly; the XML is embedded in the JSON response — no separate file endpoint.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/generate-agi" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/generate-agi" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -192,7 +192,7 @@ Save the XML to disk and upload it to **Skatteverket Mina Sidor → Tjänster
After Skatteverket confirms acceptance, store the confirmation number on the AGI:
\`\`\`bash
curl -X PATCH "https://gnubok.app/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/agi" \\
curl -X PATCH "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/salary-runs/$SR_ID/agi" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Content-Type: application/json" \\
-d '{ "submission_reference": "SKV-AGI-2026-05-A1B2C3" }'
+7 -7
View File
@@ -15,7 +15,7 @@ This is the operational companion to the [Webhooks concept page](/docs/api/webho
The response includes the HMAC signing secret **exactly once**. Capture it immediately and store it on the receiver side as an environment variable.
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/webhooks" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/webhooks" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -50,7 +50,7 @@ Response:
## 2. Implement signature verification
Use the [Node](https://gnubok.app/docs/api/webhooks#nodejs) or [Python](https://gnubok.app/docs/api/webhooks#python) sample on the concept page. The critical detail: capture the **raw request body** before any framework JSON-parses it. Re-serialising the body produces different bytes and the signature won't match.
Use the [Node](https://app.gnubok.se/docs/api/webhooks#nodejs) or [Python](https://app.gnubok.se/docs/api/webhooks#python) sample on the concept page. The critical detail: capture the **raw request body** before any framework JSON-parses it. Re-serialising the body produces different bytes and the signature won't match.
For an Express handler, that means \`express.raw({ type: 'application/json' })\` — NOT the default \`express.json()\` middleware. For FastAPI / Flask use \`request.get_data()\`. For Cloudflare Workers use \`await request.text()\` BEFORE \`request.json()\`.
@@ -59,7 +59,7 @@ For an Express handler, that means \`express.raw({ type: 'application/json' })\`
The \`:test\` verb enqueues a synthetic \`webhook.test\` delivery without driving real state. The dispatcher sends it on the next per-minute cron tick.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID/test" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID/test" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -90,7 +90,7 @@ If your receiver returns 2xx, the delivery moves to \`delivered\`. If it returns
## 4. Inspect the delivery
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID/deliveries?delivery_id=$DELIVERY_ID" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID/deliveries?delivery_id=$DELIVERY_ID" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -119,7 +119,7 @@ Response carries the captured response status and body (truncated to 4 KB), whic
Now mark a real invoice paid (or use any of the [event-emitting endpoints](/docs/api/webhooks#event-types)). The webhook handler picks up the emission and enqueues a delivery within the same request cycle.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/mark-paid" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/invoices/$INVOICE_ID/mark-paid" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -155,7 +155,7 @@ This pattern: a unique constraint on \`delivery_id\`, an INSERT-on-conflict-do-n
When a delivery exhausts its retries it's marked \`dead\`. After fixing the receiver, replay individual deliveries with:
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/webhook-deliveries/$DELIVERY_ID/retry" \\
curl -X POST "https://app.gnubok.se/api/v1/webhook-deliveries/$DELIVERY_ID/retry" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -171,7 +171,7 @@ After:
…the webhook is automatically disabled (\`active=false\`, \`disabled_reason\` set). Re-enable with:
\`\`\`bash
curl -X PATCH "https://gnubok.app/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID" \\
curl -X PATCH "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/webhooks/$WEBHOOK_ID" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Content-Type: application/json" \\
-d '{ "active": true }'
+10 -10
View File
@@ -17,7 +17,7 @@ This is the operational companion to the [Fiscal-periods reference](/docs/api/re
Before locking anything, verify the period's continuity. BFL 5 kap requires that the closing balance (UB) of year N equals the opening balance (IB) of year N+1 on every BAS 1xxx, 2xxx account.
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/continuity-check?from=2025-01-01&to=2025-12-31" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/continuity-check?from=2025-01-01&to=2025-12-31" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -45,7 +45,7 @@ Response:
BFNAR 2013:2 kap 6–7 §§ requires explanations for missing voucher numbers. Run the check:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/compliance/check?type=voucher_gaps&period=2025" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/compliance/check?type=voucher_gaps&period=2025" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -56,7 +56,7 @@ For every gap returned, file an explanation via \`POST /voucher-gap-explanations
For aktiebolag, BFL 7 kap requires every verifikation to have its underlag (receipt, faktura, kontrakt) attached. The check:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/compliance/check?type=unmatched_documents&period=2025" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/compliance/check?type=unmatched_documents&period=2025" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -67,7 +67,7 @@ Attach missing documents via \`POST /journal-entries/{id}/documents\` before loc
\`POST /fiscal-periods/{id}/lock\` blocks all writes to the period while leaving it reversible. Use this when the year's books are "done" but you may still need to add a year-end accrual entry under supervision.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/lock" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/lock" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)"
\`\`\`
@@ -87,7 +87,7 @@ Locked periods can be unlocked via \`PATCH\` with a clear reason that lands in t
This is an async operation:
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/year-end" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/year-end" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -136,7 +136,7 @@ Poll the operation; on \`succeeded\` the result block lists every voucher posted
After year-end runs, the new period (\`next_period_id\`) has IB on every balance-sheet account matching the prior period's UB. Verify:
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/trial-balance?period=2026" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/trial-balance?period=2026" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -149,7 +149,7 @@ If opening balances are wrong (rare; the engine validates before posting), use \
After the declaration, the auditor's review (if applicable), and any year-end accruals are settled, close the period. **BFL 5 kap 8 §: closing is irreversible.** No code path can re-open a closed period.
\`\`\`bash
curl -X POST "https://gnubok.app/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/close" \\
curl -X POST "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/fiscal-periods/$PERIOD_ID/close" \\
-H "Authorization: Bearer gnubok_sk_test_..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -163,7 +163,7 @@ The \`confirmation_phrase\` is a forced typed acknowledgment. The request fails
For an AB, the annual report (årsredovisning) is filed with Bolagsverket within 7 months of the fiscal-year end. v1 produces the K2/K3-formatted source data; you typeset it externally and submit via Bolagsverket Mina Sidor.
\`\`\`bash
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/annual-report?year=2025" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/annual-report?year=2025" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
@@ -175,11 +175,11 @@ The tax declaration (INK2 for AB, NE-bilaga for enskild firma) is due in March/M
\`\`\`bash
# Aktiebolag — INK2
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/ink2?year=2025" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/ink2?year=2025" \\
-H "Authorization: Bearer gnubok_sk_test_..."
# Enskild firma — NE-bilaga
curl "https://gnubok.app/api/v1/companies/$COMPANY_ID/reports/ne-bilaga?year=2025" \\
curl "https://app.gnubok.se/api/v1/companies/$COMPANY_ID/reports/ne-bilaga?year=2025" \\
-H "Authorization: Bearer gnubok_sk_test_..."
\`\`\`
+1 -1
View File
@@ -88,7 +88,7 @@ export function buildErrorReferenceMd(): string {
lines.push(' "tool": "fiscal_periods.unlock"')
lines.push(' },')
lines.push(' "details": { "fiscal_period_id": "..." },')
lines.push(' "docs_url": "https://gnubok.app/docs/api/errors#period_locked"')
lines.push(' "docs_url": "https://app.gnubok.se/docs/api/errors#period_locked"')
lines.push(' },')
lines.push(' "meta": { "request_id": "req_...", "api_version": "..." }')
lines.push('}')
+4 -4
View File
@@ -13,7 +13,7 @@ If you've used [Stripe's API](https://docs.stripe.com/api), the shape will feel
All requests authenticate with a bearer token in the \`Authorization\` header:
\`\`\`bash
curl https://gnubok.app/api/v1/companies \\
curl https://app.gnubok.se/api/v1/companies \\
-H "Authorization: Bearer gnubok_sk_live_..."
\`\`\`
@@ -29,7 +29,7 @@ Rate limit: 100 requests per minute per key, returned in \`X-RateLimit-*\` heade
## Base URL
\`\`\`
https://gnubok.app/api/v1
https://app.gnubok.se/api/v1
\`\`\`
URLs include the company id explicitly:
@@ -42,7 +42,7 @@ POST /api/v1/companies/{companyId}/invoices
A multi-company key can act on any company the underlying user is a member of — the URL is the source of truth, not a default. List the companies a key can access with:
\`\`\`bash
curl https://gnubok.app/api/v1/companies \\
curl https://app.gnubok.se/api/v1/companies \\
-H "Authorization: Bearer gnubok_sk_live_..."
\`\`\`
@@ -84,7 +84,7 @@ Errors swap \`data\` for \`error\`:
"message_en": "The selected period is locked.",
"remediation": { "description": "Unlock via /fiscal-periods/{id}/unlock or pick an open period.", "tool": "fiscal_periods.unlock" },
"details": { "fiscal_period_id": "..." },
"docs_url": "https://gnubok.app/docs/api/errors#period_locked"
"docs_url": "https://app.gnubok.se/docs/api/errors#period_locked"
},
"meta": { "request_id": "req_...", "api_version": "${API_V1_VERSION}" }
}
+4 -4
View File
@@ -24,7 +24,7 @@ Webhooks are pinned to the API version active at creation time (the \`api_versio
API requests pin per-request via the \`Gnubok-Version\` request header (planned for v1.x; today every request gets the current version):
\`\`\`bash
curl https://gnubok.app/api/v1/companies \\
curl https://app.gnubok.se/api/v1/companies \\
-H "Authorization: Bearer ..." \\
-H "Gnubok-Version: ${API_V1_VERSION}"
\`\`\`
@@ -82,7 +82,7 @@ Other endpoints **support** but don't require it. Sending one is always safe.
### Pattern
\`\`\`bash
curl https://gnubok.app/api/v1/companies/{cid}/invoices \\
curl https://app.gnubok.se/api/v1/companies/{cid}/invoices \\
-H "Authorization: Bearer ..." \\
-H "Idempotency-Key: $(uuidgen)" \\
-H "Content-Type: application/json" \\
@@ -136,8 +136,8 @@ Every successful write response carries an \`audit\` block in \`meta\`:
"api_version": "${API_V1_VERSION}",
"audit": {
"voucher_number": "A-2026-042",
"voucher_url": "https://gnubok.app/bookkeeping/...",
"audit_trail_url": "https://gnubok.app/audit/req_...",
"voucher_url": "https://app.gnubok.se/bookkeeping/...",
"audit_trail_url": "https://app.gnubok.se/audit/req_...",
"immutable_at": "2026-05-15T12:00:00Z"
}
}
+3 -3
View File
@@ -1,6 +1,6 @@
# gnubok-mcp
Connect [Claude Desktop](https://claude.ai/download) (or any stdio MCP client) to your [Accounted](https://gnubok.app) bookkeeping account. This is a thin stdio → HTTPS bridge: it forwards JSON-RPC over stdio to the hosted Accounted MCP server, which exposes 90+ bookkeeping tools (invoices, transactions, VAT/momsdeklaration, payroll, reports, year-end).
Connect [Claude Desktop](https://claude.ai/download) (or any stdio MCP client) to your [Accounted](https://app.gnubok.se) bookkeeping account. This is a thin stdio → HTTPS bridge: it forwards JSON-RPC over stdio to the hosted Accounted MCP server, which exposes 90+ bookkeeping tools (invoices, transactions, VAT/momsdeklaration, payroll, reports, year-end).
Write tools stage a pending operation that you confirm before anything is booked — the bridge never books on its own.
@@ -45,11 +45,11 @@ Restart Claude Desktop. The Accounted tools appear in the client and you can sta
## Alternative: claude.ai connector (no API key)
If you use **claude.ai** or Claude Desktop's custom-connector flow, you can skip this bridge entirely and add Accounted as an OAuth 2.1 custom connector instead — paste the connector URL `https://gnubok.app/api/extensions/ext/mcp-server/mcp` and authorise on the Accounted consent screen (read-only scopes by default; write scopes are ticked explicitly).
If you use **claude.ai** or Claude Desktop's custom-connector flow, you can skip this bridge entirely and add Accounted as an OAuth 2.1 custom connector instead — paste the connector URL `https://app.gnubok.se/api/extensions/ext/mcp-server/mcp` and authorise on the Accounted consent screen (read-only scopes by default; write scopes are ticked explicitly).
## Docs
Full setup, sample prompts, and a 10-minute reviewer test: **[Connect with Claude](https://gnubok.app/docs/api/connect-claude)**.
Full setup, sample prompts, and a 10-minute reviewer test: **[Connect with Claude](https://app.gnubok.se/docs/api/connect-claude)**.
## License