# Go-live

Moving from sandbox to production. Prerequisite: `GET /partner/v1/sandbox/verification` returns `"readyForProduction": true` — go-live requests without it are sent back to the sandbox.

## 1. Get a production key

Production keys (`blx_live_`) are issued by Bilnex, not self-serve:

1. Email **partners@bilnex.io** with: your company details, the ERP name (same as the `erpName` you provisioned with), and the **full passing verification JSON** pasted into the email (the output of `GET /partner/v1/sandbox/verification` with `readyForProduction: true`).
2. Sign the partner agreement Bilnex sends back (data processing + acceptable use).
3. Bilnex issues the `blx_live_` key over a secure channel. Like sandbox keys, it is shown once — store it in your production secret manager immediately.

The production key is bound to the real customer companies that authorize your ERP; `GET /partner/v1/me` on production lists them.

## 2. Real channel activation in production

The sandbox simulates activations that are real-world processes in production. Before a production company can use each rail, these must be completed (in the Bilnex product, by the customer — your integration does not automate them, but must expect companies where they are not yet done):

| Activation | What actually happens |
|---|---|
| Company onboarding | The person connecting the company passes **representative-rights verification against the Estonian business registry** — only a verified legal representative can activate invoicing channels for a company. |
| E-invoice receiving | The company makes a **receiving-operator election**: exactly one operator per company is registered in the registry as its e-invoice receiver. Until elected, the company cannot receive operator-channel e-invoices (and other companies' capability checks for it return `eInvoiceCapable: false`). |
| Peppol | **Peppol registration** for the company's participant ID (`0191:<regCode>`): CREATE when the company has never been on Peppol, or MIGRATE when it is registered with another access point. Migration follows the Peppol change-of-access-point process and takes longer. |
| Sending invoices | A **bank account with IBAN + BIC is required** on the company before invoices can be issued (the account is printed on the invoice and carried in the e-invoice XML). |

Practical consequence for your integration: in production, capability checks return real registry facts that change over time, sends can fail with 422 `customer_not_einvoice_capable` for customers that were capable last month, and newly-connected companies may not be able to send until their bank account and verification are in place. The sandbox fixture behaviors exist precisely so your code already handles all of this.

## 3. Sandbox vs production — the canonical differences

| Aspect | Sandbox | Production |
|---|---|---|
| E-invoice / Peppol rails | Simulated, instant delivery to the receiver company | Real operator/Peppol network timing (seconds to minutes; still no `DELIVERED` status — `SENT` stays terminal) |
| Email | Intercepted at `/partner/v1/sandbox/emails`, NEVER delivered | Really delivered to the recipient |
| Counterparties | Fixed fixtures (`95999901/02/03`) + your two sandbox companies | Real companies in real registries |
| Capability checks | Fixed fixture behaviors | Live registry lookups that change over time |
| Channel activation | Automatic — sandbox companies come pre-activated | Verified: representative rights, operator election, Peppol registration, bank account |
| API key | Self-serve, 2-day TTL (claimable to 30) | Issued by Bilnex, no TTL, rotated on request |
| `/partner/v1/sandbox/*` | Available | **404** (`sandbox_only`) |
| `SEEN` status | Via `POST /partner/v1/sandbox/trigger` `invoice_seen` | Real tracking-pixel opens (best-effort) |

Everything else — paths, payloads, status lifecycles, error envelope, rate-limit headers — is identical by design.

## 4. Switching your integration

Exactly two configuration values change:

```
BILNEX_BASE_URL=https://api.app.bilnex.io    # was https://sandbox.bilnex.io
BILNEX_API_KEY=blx_live_...                  # was blx_sbx_...
```

Plus one code requirement: every call to `/partner/v1/sandbox/*` (state, reset, claim, emails, verification, trigger) must be gated behind an environment flag — in production those paths return 404 `sandbox_only`, and an importer that depends on them will break.

## 5. Production smoke test

After switching, run a minimal smoke test. Production has real customers and real deliveries — test accordingly.

**Safe (read-only or reversible, run these):**

- `GET /partner/v1/me` — key works, correct companies listed.
- `GET /partner/v1/customers/{regCode}/e-invoice-capability` — for a real counterparty you know.
- `POST /partner/v1/invoices` — creating is safe; an unsent invoice is invisible to the customer.
- `GET /partner/v1/invoices/{id}/pdf` — render check.
- `GET /partner/v1/purchase-invoices?since=...` — poller works against production data.
- `POST /partner/v1/purchase-invoices/{id}/mark-exported` — only for documents you genuinely imported.

**With care:**

- `POST /partner/v1/invoices/{id}/send` with `channel: "EMAIL"` and `"to"` set to **your OWN email address only** — one send, verify receipt, done.

**Never:**

- Any `/partner/v1/sandbox/*` call (404 anyway — but code attempting it is a bug).
- Bulk test sends of any kind.
- `E_INVOICE`/`PEPPOL` test sends to third parties — a delivered e-invoice is a real legal document in someone's accounting inbox and cannot be unsent.

## 6. Key rotation and revocation

- **Rotation**: request a new key from partners@bilnex.io. Both keys stay valid during an overlap window (agreed at rotation, typically 7 days) — deploy the new key, confirm traffic, then Bilnex retires the old one. Plan for zero-downtime rotation from day one by reading the key from config at request time, not process start.
- **Storage**: production keys live in a secret manager (AWS Secrets Manager, Vault, or equivalent) — never in environment files committed to the repo, never in frontend/mobile code.
- **On leak**: if the key appears in a log, a repo, a ticket, or an error report — treat it as compromised. Email partners@bilnex.io for immediate revocation + reissue; do not wait for evidence of misuse. Sandbox keys need no such ceremony: reset or let them expire.
- Monitor `X-RateLimit-Remaining` and 401s in your integration's logs — a sudden stream of 401 `invalid_api_key` after a rotation means a stale key is still deployed somewhere.

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`.
