# Getting started

> Base URL, your first call, and the no-sandbox note.

Source: https://invoia.io/developers/api

The Invoia Public API lets you drive invoicing and revenue recognition
from your own tooling — the same product you operate through our UI,
now callable from your PM tool or automation stack.

## Base URL [#base-url]

```
https://invoia.io/api/v1
```

All endpoints live under this prefix. The URL major (`/v1`) is
additive-only — new fields and endpoints may be added, but nothing you
already integrate against will break within a major.

## Your first call [#your-first-call]

Mint an API key in **Settings → Developers** (an admin only permission).
The raw `ivk_…` secret is shown once at creation. Store it in your
integration's secret manager and drop the value into an
`Authorization: Bearer …` header.

```bash
curl https://invoia.io/api/v1/config \
  -H "Authorization: Bearer $INVOIA_API_KEY"
```

```js
const res = await fetch('https://invoia.io/api/v1/config', {
  headers: { Authorization: `Bearer ${process.env.INVOIA_API_KEY}` },
})
const config = await res.json()
console.log(config.base_currency) // "DKK"
```

## What each key can do [#what-each-key-can-do]

A key is bound to **one connected Dinero integration** and to a
**scope**:

| Scope        | Verbs | Use case                                              |
| ------------ | ----- | ----------------------------------------------------- |
| `read`       | `GET` | Dashboards, BI, read-only sync from PM tool           |
| `read_write` | all   | Full drive: create/edit/issue invoices, register work |

A `read` key on a write endpoint returns `403` with a typed error code —
no ambiguity to parse.

## There is no sandbox [#there-is-no-sandbox]

Invoia does not host a test mode. There are no `ivk_test_` keys and no
hosted fake-Dinero sandbox. **Build against your live integration using a
throwaway customer and product** — a name like `Test Corp` and a product
`INTEGRATION-TEST` are fine. When your integration is working, delete
those records the same way you would any other resource.

We chose no-sandbox deliberately: a sandbox that drifts from production
is worse than a live account you can control. Every failure mode you
would hit in test — an unbookable credit note, a rate limit, a Dinero
timeout — is a failure mode you can hit in production, and there is no
substitute for exercising the real path.

## Where to go next [#where-to-go-next]

* **[Quickstart](/developers/api/quickstart)** — the same first call in
  curl, Node and Python, end to end.
* **[Authentication](/developers/api/authentication)** — key format,
  headers, rotation.
* **[external\_id and idempotency](/developers/api/external-id)** — how
  Invoia correlates your resources with theirs without you ever holding a
  Invoia UUID.
* **[Work registration](/developers/api/work-registration)** — sending
  hours and completion into the same recognition engine the UI uses.
* **[Issuance and auto-send](/developers/api/issuance)** — driving
  invoice issuance explicitly, or letting the cron do it.
* **[Webhooks](/developers/api/webhooks)** — signed events for changes
  your integration did not trigger (auto-issued invoices, month-end
  accruals, Dinero reconcile writes).
* **[Errors](/developers/api/errors)** — the machine-readable envelope
  and every code you can branch on.
* **[Pagination](/developers/api/pagination)** — cursor-based lists
  with `updated_since` filtering.
