Docs menu

Quickstart

Create a key, make one call, page through the result. Five minutes, no SDK needed.

The Integrations API is a JSON REST API at https://api.officehero.io. Every request is made with an API key that belongs to one OfficeHero company (tenant) and carries the scopes you chose for it.

1. Create an API key

You need to be a tenant owner or admin (the identity.api_keys.admin permission).

  1. Open the Fleet, HR or Finance app and go to Settings → API keys.
  2. Click Create API key, give it a name you will recognise later (for example “ERP sync — production”) and an expiry date if you want one.
  3. Tick only the scopes your integration needs — for this quickstart, int:fin.invoices:read. See Scopes for the full list.
  4. Copy the key. It is shown once and looks like this (oh_live_, a 12-character prefix, _, a 43-character secret):
oh_live_a1b2c3d4e5f6_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Store it like a password — in your secret manager or deployment environment, never in source code or in a browser or mobile app. The first time a key is used, your company’s admins get a notification.

2. Make your first call

List the five most recent invoices:

curl "https://api.officehero.io/v1/invoices?limit=5" \
  -H "Authorization: Bearer $OFFICEHERO_API_KEY" \
  -H "OH-Version: 2026-05-16"
const res = await fetch('https://api.officehero.io/v1/invoices?limit=5', {
  headers: {
    Authorization: `Bearer ${process.env.OFFICEHERO_API_KEY}`,
    'OH-Version': '2026-05-16',
  },
});
if (!res.ok) throw new Error(`${res.status}: ${(await res.json()).detail}`);
const page = await res.json();
console.log(page.data.map((invoice) => invoice.number));
import os
import requests

res = requests.get(
    "https://api.officehero.io/v1/invoices",
    params={"limit": 5},
    headers={
        "Authorization": f"Bearer {os.environ['OFFICEHERO_API_KEY']}",
        "OH-Version": "2026-05-16",
    },
    timeout=30,
)
res.raise_for_status()
for invoice in res.json()["data"]:
    print(invoice["number"], invoice["status"], invoice["total_minor"])
<?php
$ch = curl_init('https://api.officehero.io/v1/invoices?limit=5');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('OFFICEHERO_API_KEY'),
        'OH-Version: 2026-05-16',
    ],
]);
$page = json_decode(curl_exec($ch), true, 512, JSON_THROW_ON_ERROR);
foreach ($page['data'] as $invoice) {
    echo $invoice['number'], ' ', $invoice['status'], PHP_EOL;
}

OH-Version is optional — without it you get the oldest supported version, which today is the only one. Sending it means a future version will never change your responses without you opting in. See Versioning.

3. Read the response

Every list answers with the same envelope:

{
  "data": [
    {
      "id": "0199c3a2-4b7e-7f30-9c2e-6a8d4f1b2c01",
      "number": "INV-2026-00418",
      "status": "partial",
      "currency": "EUR",
      "total_minor": 147500,
      "balance_minor": 97500,
      "issue_date": "2026-09-14",
      "created_at": "2026-09-14T08:30:00Z"
    }
  ],
  "next_cursor": "eyJpZCI6IjAxOTljM2EyLTRiN2UtN2YzMC05YzJlLTZhOGQ0ZjFiMmMwMSIsInRzIjoiMjAyNi0wOS0xNFQwODozMDowMC4wMDAwMDArMDA6MDAifQ",
  "has_more": true
}

(The invoice is shortened here — the reference lists every field.) Money is an integer in the currency’s minor unit: 147500 EUR is €1,475.00. Timestamps are UTC. See Data conventions.

4. Get the next page

Pass next_cursor back as cursor until has_more is false:

curl "https://api.officehero.io/v1/invoices?limit=5&cursor=eyJpZCI6…" \
  -H "Authorization: Bearer $OFFICEHERO_API_KEY"

See Pagination.

5. Try it in the browser

The API reference can send real requests: paste your key into Authentication, open an endpoint and press Test Request. The key stays in that browser tab’s memory — it is never stored and never sent anywhere but the API. Requests are real, so use a key with read scopes and an expiry for exploring.

What next