# Quickstart

The entire happy path against the sandbox, in order. Every step is a runnable curl. Completing steps 1–13 makes `GET /partner/v1/sandbox/verification` return `"readyForProduction": true` for all 12 required checks.

Base URL for everything on this page: `https://sandbox.bilnex.io`. Auth header on every call except step 1: `Authorization: Bearer <YOUR_API_KEY>`.

## 1. Provision a key

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/sandbox \
  -H "Content-Type: application/json" \
  -d '{"email":"dev@erp.example","erpName":"AwesomeERP","ref":"agent"}'
```

```json
{
  "apiKey": "blx_sbx_9tK4mQv7Xw2eR5pLnA8cJ1bYfD3hG6sZ",
  "keyId": "7c1f0a52-3b8d-4e69-9a24-5d0e7b61c3af",
  "keyPrefix": "blx_sbx_9tK4",
  "expiresAt": "2026-08-13T09:00:00Z",
  "limits": {
    "requestsPerMinute": 60,
    "requestsPerDay": 5000,
    "maxInvoices": 500,
    "maxEmails": 200
  },
  "companies": {
    "sender": {
      "companyId": "b7e486ae-59f0-4f3a-9d5c-1e8a2f6c4d21",
      "name": "Valge Klaar OÜ",
      "regCode": "95000002",
      "peppolId": "0191:95000002"
    },
    "receiver": {
      "companyId": "4a1c7b9e-2d5f-4e8a-b3c6-9f0d7e5a8b42",
      "name": "Sinilille Kaubandus OÜ",
      "regCode": "95000003"
    }
  },
  "fixtures": [
    { "name": "Sandbox Capable OÜ", "regCode": "95999901", "behavior": "accepts_einvoice" },
    { "name": "Sandbox Paper OÜ", "regCode": "95999902", "behavior": "not_einvoice_capable" },
    { "name": "Sandbox Rejector OÜ", "regCode": "95999903", "behavior": "rejects_einvoice" }
  ],
  "urls": {
    "docs": "https://sandbox.bilnex.io/docs/quickstart.md",
    "verification": "https://sandbox.bilnex.io/partner/v1/sandbox/verification",
    "openapi": "https://sandbox.bilnex.io/partner/v1/openapi.json",
    "claim": "https://sandbox.bilnex.io/partner/v1/sandbox/claim"
  }
}
```

`apiKey` is shown once. Store it in server-side configuration only. `<RECEIVER_COMPANY_ID>` below = `companies.receiver.companyId`.

## 2. Auth check — `AUTH_OK`

```bash
curl -s https://sandbox.bilnex.io/partner/v1/me \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "environment": "sandbox",
  "keyId": "7c1f0a52-3b8d-4e69-9a24-5d0e7b61c3af",
  "keyExpiresAt": "2026-08-13T09:00:00Z",
  "actingCompany": {
    "companyId": "b7e486ae-59f0-4f3a-9d5c-1e8a2f6c4d21",
    "name": "Valge Klaar OÜ",
    "regCode": "95000002",
    "role": "ADMIN"
  },
  "companies": [
    { "companyId": "b7e486ae-59f0-4f3a-9d5c-1e8a2f6c4d21", "role": "ADMIN" },
    { "companyId": "4a1c7b9e-2d5f-4e8a-b3c6-9f0d7e5a8b42", "role": "ADMIN" }
  ],
  "limits": {
    "requestsPerMinute": 60,
    "requestsPerDay": 5000,
    "maxInvoices": 500,
    "maxEmails": 200
  },
  "usage": {
    "requestsToday": 148,
    "sendsToday": 3,
    "emailsCaptured": 5
  }
}
```

## 3. Capability check, capable — `CAPABILITY_CHECKED_CAPABLE`

```bash
curl -s https://sandbox.bilnex.io/partner/v1/customers/95000003/e-invoice-capability \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "regCode": "95000003",
  "name": "Sinilille Kaubandus OÜ",
  "eInvoiceCapable": true,
  "operator": "Finbite",
  "peppolCapable": true,
  "peppolId": "0191:95000003",
  "recommendedChannel": "E_INVOICE",
  "checkedAt": "2026-08-06T09:02:10Z"
}
```

## 4. Capability check, not capable — `CAPABILITY_CHECKED_NOT_CAPABLE`

```bash
curl -s https://sandbox.bilnex.io/partner/v1/customers/95999902/e-invoice-capability \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "regCode": "95999902",
  "name": "Sandbox Paper OÜ",
  "eInvoiceCapable": false,
  "operator": null,
  "peppolCapable": false,
  "peppolId": null,
  "recommendedChannel": "EMAIL",
  "checkedAt": "2026-08-06T09:02:41Z"
}
```

Branch on `eInvoiceCapable`: `false` → send via `EMAIL` (step 10).

## 5. Create an invoice — `INVOICE_CREATED`

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/invoices \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 6d1f9a3e-8c47-4b2a-9d05-e1f7a2c4b8d0" \
  -d '{
    "customer": {
      "name": "Sinilille Kaubandus OÜ",
      "regCode": "95000003",
      "email": "arved@sinilille.example",
      "address": "Sinilille tee 4, 10115 Tallinn, Estonia"
    },
    "date": "2026-08-06",
    "dueDate": "2026-08-20",
    "currency": "EUR",
    "language": "ET",
    "items": [
      {
        "description": "Consulting services, July 2026",
        "quantity": 10.00,
        "unit": "h",
        "price": 95.00,
        "vatRate": 24
      }
    ]
  }'
```

```json
{
  "id": "8c2a91d4-6e3b-4f7a-a1d9-5b8e2c7f0a63",
  "number": "2026-0001",
  "status": "SAVED",
  "category": "PDF",
  "date": "2026-08-06",
  "dueDate": "2026-08-20",
  "currency": "EUR",
  "language": "ET",
  "customer": {
    "name": "Sinilille Kaubandus OÜ",
    "regCode": "95000003",
    "email": "arved@sinilille.example",
    "address": "Sinilille tee 4, 10115 Tallinn, Estonia"
  },
  "items": [
    {
      "description": "Consulting services, July 2026",
      "quantity": 10.00,
      "unit": "h",
      "price": 95.00,
      "vatRate": 24,
      "totalPrice": 950.00
    }
  ],
  "netAmount": 950.00,
  "vatAmount": 228.00,
  "vatSummary": [
    { "rate": 24, "base": 950.00, "amount": 228.00 }
  ],
  "totalAmount": 1178.00,
  "createdDate": "2026-08-06T09:05:12Z"
}
```

Server-computed totals are authoritative — never recompute them in the ERP.

## 6. Fetch the PDF — `PDF_FETCHED`

```bash
curl -s https://sandbox.bilnex.io/partner/v1/invoices/8c2a91d4-6e3b-4f7a-a1d9-5b8e2c7f0a63/pdf \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "pdfUrl": "https://sandbox.bilnex.io/files/invoices/8c2a91d4-6e3b-4f7a-a1d9-5b8e2c7f0a63.pdf?sig=6f0a2b7c8d15e3a9&exp=1786359912",
  "expiresAt": "2026-08-06T09:20:12Z"
}
```

## 7. Send as e-invoice — `EINVOICE_SENT`

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/invoices/8c2a91d4-6e3b-4f7a-a1d9-5b8e2c7f0a63/send \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0b3c8e5d-2f7a-4c19-8a6b-d4e1f9a0c752" \
  -d '{"channel":"E_INVOICE"}'
```

```json
{
  "id": "8c2a91d4-6e3b-4f7a-a1d9-5b8e2c7f0a63",
  "status": "SENT",
  "category": "E_INVOICE",
  "channel": "E_INVOICE",
  "sentAt": "2026-08-06T09:06:30Z"
}
```

`SENT` is terminal for `E_INVOICE` — nothing further to poll.

## 8. List purchase invoices at the receiver — `EINVOICE_RECEIVED_AT_RECEIVER`, `PURCHASE_LISTED`

```bash
curl -s "https://sandbox.bilnex.io/partner/v1/purchase-invoices?since=2026-08-06T00:00:00Z" \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "X-Company-Id: <RECEIVER_COMPANY_ID>"
```

```json
{
  "items": [
    {
      "id": "d94b7f2a-1c5e-4a8b-9e3d-6f0a2b7c8d15",
      "status": "NEW",
      "source": "E_INVOICE",
      "sender": { "name": "Valge Klaar OÜ", "regCode": "95000002" },
      "invoiceNumber": "2026-0001",
      "date": "2026-08-06",
      "dueDate": "2026-08-20",
      "currency": "EUR",
      "netAmount": 950.00,
      "vatAmount": 228.00,
      "totalAmount": 1178.00,
      "receivedAt": "2026-08-06T09:06:31Z"
    }
  ],
  "page": 1,
  "pageSize": 50,
  "hasMore": false,
  "nextSince": "2026-08-06T09:06:31Z"
}
```

Persist `nextSince` for the next poll. Dedupe by `id`.

## 9. Mark exported — `MARKED_EXPORTED`

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/purchase-invoices/d94b7f2a-1c5e-4a8b-9e3d-6f0a2b7c8d15/mark-exported \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "X-Company-Id: <RECEIVER_COMPANY_ID>"
```

```json
{
  "id": "d94b7f2a-1c5e-4a8b-9e3d-6f0a2b7c8d15",
  "status": "EXPORTED",
  "exportedAt": "2026-08-06T09:08:02Z"
}
```

Mandatory after every ERP import. Idempotent.

## 10. Create + send an EMAIL invoice to the not-capable customer — `EMAIL_SENT`, `NOT_CAPABLE_FALLBACK`

Back as the sender (no `X-Company-Id`):

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/invoices \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 91e4d7c2-5a0b-4f38-b6d9-3c8a1e7f2b04" \
  -d '{
    "customer": {
      "name": "Sandbox Paper OÜ",
      "regCode": "95999902",
      "email": "billing@sandbox-paper.example"
    },
    "date": "2026-08-06",
    "dueDate": "2026-08-20",
    "currency": "EUR",
    "language": "ET",
    "items": [
      {
        "description": "Monthly service fee, August 2026",
        "quantity": 1.00,
        "unit": "pcs",
        "price": 49.00,
        "vatRate": 24
      }
    ]
  }'
```

```json
{
  "id": "f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21",
  "number": "2026-0002",
  "status": "SAVED",
  "category": "PDF",
  "date": "2026-08-06",
  "dueDate": "2026-08-20",
  "currency": "EUR",
  "language": "ET",
  "customer": {
    "name": "Sandbox Paper OÜ",
    "regCode": "95999902",
    "email": "billing@sandbox-paper.example",
    "address": null
  },
  "items": [
    {
      "description": "Monthly service fee, August 2026",
      "quantity": 1.00,
      "unit": "pcs",
      "price": 49.00,
      "vatRate": 24,
      "totalPrice": 49.00
    }
  ],
  "netAmount": 49.00,
  "vatAmount": 11.76,
  "vatSummary": [
    { "rate": 24, "base": 49.00, "amount": 11.76 }
  ],
  "totalAmount": 60.76,
  "createdDate": "2026-08-06T09:10:03Z"
}
```

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/invoices/f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21/send \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: c5a9b0d3-7e21-4f6f-8e6d-1b4a2c4d0e97" \
  -d '{"channel":"EMAIL","to":"billing@sandbox-paper.example"}'
```

```json
{
  "id": "f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21",
  "status": "SENT",
  "category": "PDF",
  "channel": "EMAIL",
  "sentAt": "2026-08-06T09:10:44Z"
}
```

`NOT_CAPABLE_FALLBACK` passes because the same regCode (`95999902`) was capability-checked `false` in step 4 and then invoiced via `EMAIL`.

## 11. Fetch the intercepted email — `EMAIL_FETCHED_FROM_INTERCEPT`

Sandbox email is never delivered; read it here:

```bash
curl -s https://sandbox.bilnex.io/partner/v1/sandbox/emails \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "items": [
    {
      "id": "eml_4c8d15a2b7f0",
      "to": "billing@sandbox-paper.example",
      "from": "invoices@bilnex.io",
      "subject": "Invoice 2026-0002 from Valge Klaar OÜ",
      "invoiceId": "f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21",
      "sentAt": "2026-08-06T09:10:44Z",
      "attachments": [
        { "filename": "invoice-2026-0002.pdf", "contentType": "application/pdf" }
      ]
    }
  ],
  "page": 1,
  "pageSize": 50,
  "hasMore": false
}
```

## 12. Trigger and handle SEEN — `INVOICE_SEEN_HANDLED` (optional)

```bash
curl -s -X POST https://sandbox.bilnex.io/partner/v1/sandbox/trigger \
  -H "Authorization: Bearer <YOUR_API_KEY>" \
  -H "Content-Type: application/json" \
  -d '{"event":"invoice_seen","invoiceId":"f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21"}'
```

```json
{
  "event": "invoice_seen",
  "status": "triggered",
  "invoiceId": "f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21"
}
```

Then fetch the invoice and observe `"status": "SEEN"`:

```bash
curl -s https://sandbox.bilnex.io/partner/v1/invoices/f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21 \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "id": "f3b9d0e7-4a2c-4d1b-8e6f-7c5a9b0d3e21",
  "number": "2026-0002",
  "status": "SEEN",
  "category": "PDF",
  "date": "2026-08-06",
  "dueDate": "2026-08-20",
  "currency": "EUR",
  "language": "ET",
  "customer": {
    "name": "Sandbox Paper OÜ",
    "regCode": "95999902",
    "email": "billing@sandbox-paper.example",
    "address": null
  },
  "items": [
    {
      "description": "Monthly service fee, August 2026",
      "quantity": 1.00,
      "unit": "pcs",
      "price": 49.00,
      "vatRate": 24,
      "totalPrice": 49.00
    }
  ],
  "netAmount": 49.00,
  "vatAmount": 11.76,
  "vatSummary": [
    { "rate": 24, "base": 49.00, "amount": 11.76 }
  ],
  "totalAmount": 60.76,
  "createdDate": "2026-08-06T09:10:03Z"
}
```

## 13. Verification — the stopping condition

```bash
curl -s https://sandbox.bilnex.io/partner/v1/sandbox/verification \
  -H "Authorization: Bearer <YOUR_API_KEY>"
```

```json
{
  "checks": [
    { "id": "AUTH_OK", "required": true, "status": "pass", "detail": "GET /partner/v1/me succeeded", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/authentication.md" },
    { "id": "CAPABILITY_CHECKED_CAPABLE", "required": true, "status": "pass", "detail": "Capability checked for 95000003 (capable)", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "CAPABILITY_CHECKED_NOT_CAPABLE", "required": true, "status": "pass", "detail": "Capability checked for 95999902 (not capable)", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "INVOICE_CREATED", "required": true, "status": "pass", "detail": "2 invoices created", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "PDF_FETCHED", "required": true, "status": "pass", "detail": "PDF fetched for 2026-0001", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "EINVOICE_SENT", "required": true, "status": "pass", "detail": "2026-0001 sent via E_INVOICE", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "EINVOICE_RECEIVED_AT_RECEIVER", "required": true, "status": "pass", "detail": "Purchase invoice d94b7f2a received at Sinilille Kaubandus OÜ", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/receiving-invoices.md" },
    { "id": "PURCHASE_LISTED", "required": true, "status": "pass", "detail": "Purchase invoices listed with since parameter", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/receiving-invoices.md" },
    { "id": "MARKED_EXPORTED", "required": true, "status": "pass", "detail": "d94b7f2a marked exported", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/receiving-invoices.md" },
    { "id": "EMAIL_SENT", "required": true, "status": "pass", "detail": "2026-0002 sent via EMAIL", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/email-invoices.md" },
    { "id": "EMAIL_FETCHED_FROM_INTERCEPT", "required": true, "status": "pass", "detail": "Intercepted email eml_4c8d15a2b7f0 fetched", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/email-invoices.md" },
    { "id": "NOT_CAPABLE_FALLBACK", "required": true, "status": "pass", "detail": "95999902 checked not capable, then invoiced via EMAIL", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/sending-invoices.md" },
    { "id": "PEPPOL_SENT", "required": false, "status": "pending", "detail": "No PEPPOL send yet", "fixHint": "POST /partner/v1/invoices/{id}/send with channel PEPPOL to a peppolCapable customer", "docsUrl": "https://sandbox.bilnex.io/docs/peppol.md" },
    { "id": "PEPPOL_RECEIVED", "required": false, "status": "pending", "detail": "No PEPPOL purchase invoice listed yet", "fixHint": "Send via PEPPOL to the receiver company (or trigger inbound_peppol), then list its purchase invoices", "docsUrl": "https://sandbox.bilnex.io/docs/peppol.md" },
    { "id": "INVOICE_SEEN_HANDLED", "required": false, "status": "pass", "detail": "2026-0002 observed in status SEEN after open", "fixHint": null, "docsUrl": "https://sandbox.bilnex.io/docs/email-invoices.md" }
  ],
  "readyForProduction": true,
  "nextSteps": [
    "All 12 required checks pass. Optional: PEPPOL_SENT, PEPPOL_RECEIVED remain pending.",
    "See https://sandbox.bilnex.io/docs/go-live.md for a production key."
  ]
}
```

Do not report the integration complete until this returns `"readyForProduction": true`. If a check fails, read its `fixHint` and `docsUrl`, fix the integration code, and re-run. When it passes, continue with [go-live](https://sandbox.bilnex.io/docs/go-live.md).

API version 2026-08-01. /partner/v1 changes are additive-only; see [versioning-policy](https://sandbox.bilnex.io/docs/versioning-policy.md).

---
**Building with a coding agent?** Start from [agents.md](https://sandbox.bilnex.io/agents.md) or install the skill: `npx skills add https://sandbox.bilnex.io`. Machine-readable index: [llms.txt](https://sandbox.bilnex.io/llms.txt). Every page on this site is also plain markdown — append `.md`.
