Skip to content
In this section

Quickstart

From a fresh key to listing invoices and downloading a PDF.

This walks from a fresh API key to a working integration. Every example is copy-pasteable; replace the key and ids with your own.

1. Get a key

In the Fynex dashboard, open Integration in the left-hand menu and issue a secret key from the API keys card.

  • sk_test_… — authenticates while your account is in demo mode.
  • sk_live_… — authenticates once your account is live.

An account is in exactly one of those modes, so exactly one of the two key environments works at any time.

Keys are stored only as hashes, so a key is shown once, at creation. If you lose it, regenerate — there is no recovery. Keep keys server-side: they carry full read and write access to your billing data.

2. Set your base URL

Every endpoint sits under the path /billing-api/v1. The host depends on the environment you were onboarded to, so the examples below use a variable:

export FYNEX_API_BASE="https://api.fynex.ai/billing-api/v1"
export FYNEX_API_KEY="sk_test_4f6f..."
Environment Host
Production https://api.fynex.ai — a sk_live_ key is accepted only by the environment that issued it. The OpenAPI document's servers block lists the origin of the deployment you are reading from first, so a generated client needs no manual host configuration.

You are reading these docs on the same host the API runs on, so /billing-api/v1/openapi.json and /billing-api/v1/docs are always reachable relative to wherever this page is served.

3. Make your first call

GET /contracts is the safest first request — it needs no ids and tells you whether your key, environment, and network path all work:

curl -s $FYNEX_API_BASE/contracts \
  -H "Authorization: Bearer $FYNEX_API_KEY"
{
  "contracts": [
    {
      "contractId": 42,
      "contractNumber": "UK2607AA",
      "version": 1,
      "sellerCustomerId": 7,
      "currency": "EUR",
      "status": "active",
      "startDate": "2026-01-01",
      "customerName": "Ada Lovelace",
      "customerCompanyName": "Harbour Group BV"
    }
  ]
}

contractId is the key to every per-contract endpoint that follows.

If instead you get:

  • 401 — the header is missing or the key is wrong. The format is Authorization: Bearer sk_live_…; a bare key without Bearer fails.
  • 403 — the key is valid but the seller account is not active. Check the account status in the dashboard.
  • an empty contracts array — the key works, but this account has no contracts yet.

4. List invoices

curl -s "$FYNEX_API_BASE/invoices?limit=5" \
  -H "Authorization: Bearer $FYNEX_API_KEY"
{
  "invoices": [
    {
      "id": 4180,
      "contractId": 42,
      "sellerCustomerId": 7,
      "origin": "usage",
      "invoiceNumber": "UK2607AA-2608AAB",
      "jurisdiction": "UK",
      "invoiceType": "standard",
      "status": "sent",
      "currency": "EUR",
      "issueDate": "2026-08-01T00:00:00Z",
      "dueDate": "2026-08-15T00:00:00Z",
      "subtotalMinor": 10000,
      "taxTotalMinor": 2000,
      "grandTotalMinor": 12000,
      "creditAppliedMinor": 0,
      "collectibleMinor": 12000,
      "creditSettledMinor": 0,
      "reverseCharge": false,
      "paymentLinkId": 991
    }
  ],
  "hasMore": true,
  "nextCursor": 4180,
  "nextBeforeId": 4180
}

Two things to internalize right now, because they cause most integration bugs:

  • Amounts are integers in minor units. 12000 in EUR is €120.00. Never parse them as floats.
  • grandTotalMinor is the document total, collectibleMinor is what collection asks the customer for. They differ when stored credit funded part of the invoice. Neither drops to zero once the invoice is paid — to decide "does this customer still owe us money", read status.
  • creditSettledMinor is not a payment total. It counts only stored credit drawn down, so a card-paid invoice reports 0 there.

5. Get one invoice with its lines

curl -s $FYNEX_API_BASE/invoices/4180 \
  -H "Authorization: Bearer $FYNEX_API_KEY"
{
  "invoice": { "id": 4180, "invoiceNumber": "UK2607AA-2608AAB", "...": "..." },
  "lines": [
    {
      "position": 1,
      "description": "API calls over allowance",
      "quantity": "250",
      "unitPriceMinor": 40,
      "discountMinor": 0,
      "netAmountMinor": 10000,
      "taxCategory": "standard",
      "taxRate": "20",
      "taxAmountMinor": 2000,
      "sourceRef": "usage:api_calls:2026-07"
    }
  ]
}

quantity and taxRate are decimal strings — they carry fractional precision that a JSON number would round. Feed them to a decimal type, not a float.

6. Download the PDF

curl -s $FYNEX_API_BASE/invoices/4180/pdf \
  -H "Authorization: Bearer $FYNEX_API_KEY" \
  -o invoice-UK2607AA-2608AAB.pdf

The response is application/pdf bytes with a Content-Disposition filename. It renders from the document's frozen payload, so a PDF fetched today and one fetched next year are identical.

Next

  • Workflows shows the end-to-end recipes: collecting on an invoice, reconciling a month, watching usage against limits.
  • Pagination & Amounts covers the paging loop you will need past 20 rows.
  • Errors covers the status contract, rate limits, and retry policy.