# Getting started

> Base URL, your first call, what a key reaches, and the no-sandbox note.

Source: https://www.tabba.io/developers/api

The Tabba Sales API lets your own systems operate the Sales module of one
company: its customers and products, its invoices and recurring series, work
registration, credit notes, and the revenue recognition and month-end accrual
that read them. It is the same service the workspace calls. A write goes to
the company's accounting system first, exactly as a write in the workspace
does.

## Base URL [#base-url]

```
https://www.tabba.io/api/v1
```

Every endpoint lives under this prefix. Changes within `/api/v1` are additive:
fields, endpoints and error codes are added, and none is renamed.

The contract is published as an OpenAPI 3.1 document at
`https://www.tabba.io/api/v1/openapi.json`. It takes no key. The
[API reference](/developers/reference) is built from it.

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

An admin or a bookkeeper of the company mints an API key in the company's settings,
under Developers (`/workspace/settings/company/developers`). The raw `tba_…` key is shown once, when
it is minted. Store it in your integration's secret manager and send it as a
bearer token.

```bash
curl https://www.tabba.io/api/v1/config \
  -H "Authorization: Bearer $TABBA_API_KEY"
```

```js
const res = await fetch('https://www.tabba.io/api/v1/config', {
  headers: { Authorization: `Bearer ${process.env.TABBA_API_KEY}` },
})
const config = await res.json()
console.log(config.company_name, config.base_currency)
```

`GET /config` answers the company the key is bound to, the base currency
every figure of the company is stated in, and the two accounts the month-end
accrual moves. Both accounts are `null` until an admin has confirmed them.

## What a key reaches [#what-a-key-reaches]

A key is bound to **one connected company** and has a **scope**. The company
is on one of two accounting systems, and every endpoint behaves the same on
either: see [Accounting platforms](/developers/api/platforms).

| Scope        | Methods | Use                                                      |
| ------------ | ------- | -------------------------------------------------------- |
| `read`       | `GET`   | Dashboards, reporting, a one-way sync out of Tabba       |
| `read_write` | all     | Create and change records, register work, issue invoices |

A `read` key on a write endpoint is answered `403` with the code
`SCOPE_INSUFFICIENT`.

## What the API covers [#what-the-api-covers]

| Resource              | What a key does with it                                                        |
| --------------------- | ------------------------------------------------------------------------------ |
| Config                | Reads the company, its base currency and its accrual accounts                  |
| Users                 | Lists the people who can work in the company, and sets their `external_id`     |
| Customers, products   | Lists, creates, changes and deletes them, in the accounting system first       |
| Invoices              | Writes drafts, issues them, reads their revenue recognition                    |
| Recurring series      | Creates a series, changes its lines, reads and issues its occurrences, ends it |
| Work registrations    | Sets a person's hours and completion on a line                                 |
| Credit notes          | Credits an issued invoice in full or in part                                   |
| Recognition, accruals | Reads what a customer has earned and billed, and a month's accrual entry       |

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

There is no test mode and no test key. Build against a company you control,
with a throwaway customer and product, and delete them when you are done.

Three facts make that safe to do:

* **A draft invoice is Tabba's own record.** Nothing is asked of the
  accounting system until the invoice is issued, and a draft is deleted
  without a trace in the books.
* **A customer and a product are written to the accounting system at once.**
  Delete the ones you made for testing.
* **A new invoice has `auto_send` on unless you say otherwise.** The daily run
  issues such an invoice on its issue date. Send `auto_send: false` on every
  invoice you create while testing.

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

* **[Quickstart](/developers/api/quickstart)**: from a key to recognised
  revenue, in curl, Node and Python.
* **[Authentication](/developers/api/authentication)**: the key, its scope,
  the company it is bound to, rotation.
* **[Accounting platforms](/developers/api/platforms)**: what is identical on
  both accounting systems, and the few fields and refusals a platform decides.
* **[external\_id and idempotency](/developers/api/external-id)**: how you
  address every record by your own key, and why a retried create makes
  nothing twice.
* **[Work registration](/developers/api/work-registration)**: sending hours
  and completion into the figures the workspace shows.
* **[Issuance and auto-send](/developers/api/issuance)**: issuing an invoice
  yourself, or leaving it to the daily run.
* **[Webhooks](/developers/api/webhooks)**: signed events for changes your
  integration did not make.
* **[Pagination](/developers/api/pagination)**: cursors, and following a list
  with `updated_since`.
* **[Errors](/developers/api/errors)**: the error envelope, every code, the
  rate limits.
