# Making Your First API Request 

** Learn how to authenticate with the Karbon API using the required Authorization and AccessKey headers, make your first request to verify your credentials, and understand the account-level access model that governs all API operations. **
---

The Karbon API requires headers on every request to authenticate a request. Once you have them, you're ready to go.

## Prerequisites

- A Karbon account with API access

## Required Headers

Every request must include both of the following headers:

| Header          | Format                     | Where to find it                                                              |
| --------------- | -------------------------- | ----------------------------------------------------------------------------- |
| `Authorization` | `Bearer {token}`           | Karbon UI → Settings → Connected Apps → API Applications → your application   |
| `AccessKey`     | JWT (starts with `eyJ...`) | Karbon UI → Settings → Connected Apps → API Applications → your application   |

Both values are issued together from the same API Application in Karbon. The `Authorization` token is a 36 character long GUID. The `AccessKey` is a JWT with three
Base64URL-encoded segments separated by dots. **These two values are not interchangeable** — swapping them results in a `401`.

This guide contains example values for Authorization and AccessKey, you'll need to substitute in
your own values in order to make a successful API request.

## Base URL

```
https://api.karbonhq.com
```

All endpoints are versioned under `/v3/`.

## Making a Request

The following examples all call `GET /v3/TenantSettings` — a good smoke test that returns your
account configuration with no side effects.

### Postman / Bruno

[Postman](https://www.postman.com) and [Bruno](https://www.usebruno.com) are desktop API clients
that let you make HTTP requests without writing any code — useful for exploring the API and testing
requests interactively. Bruno is open-source and stores collections as local files; Postman is
cloud-based with a generous free tier.

1. Create a new **GET** request to `https://api.karbonhq.com/v3/TenantSettings`
2. Open the **Headers** tab and add:
  - Key: `Authorization` — Value: `Bearer 550e8400-e29b-41d4-a716-446655440000`
  - Key: `AccessKey` — Value: `<your-access-key>`
3. Send the request

**Tip:** Store your credentials in an environment and reference them as variables (e.g.
`{{authToken}}` and `{{accessKey}}`) so you don't need to repeat them on every request.

### curl

```bash
curl https://api.karbonhq.com/v3/TenantSettings \
  -H "Authorization: Bearer 550e8400-e29b-41d4-a716-446655440000" \
  -H "AccessKey: <your-access-key>"
```

### JavaScript (fetch)

```javascript
const TOKEN = process.env.KARBON_TOKEN;
const ACCESS_KEY = process.env.KARBON_ACCESS_KEY;

const response = await fetch("https://api.karbonhq.com/v3/TenantSettings", {
  headers: {
    "Authorization": `Bearer ${TOKEN}`,
    "AccessKey": ACCESS_KEY,
  },
});

if (!response.ok) {
  throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}

const data = await response.json();
console.log(data);
```

### JavaScript (axios)

```javascript
import axios from "axios";

const client = axios.create({
  baseURL: "https://api.karbonhq.com/v3",
  headers: {
    "Authorization": `Bearer ${process.env.KARBON_TOKEN}`,
    "AccessKey": process.env.KARBON_ACCESS_KEY,
  },
});

const {data} = await client.get("/TenantSettings");
console.log(data);
```

### Python (requests)

```python
import os
import requests

headers = {
    "Authorization": f"Bearer {os.environ['KARBON_TOKEN']}",
    "AccessKey": os.environ["KARBON_ACCESS_KEY"],
}

response = requests.get(
    "https://api.karbonhq.com/v3/TenantSettings",
    headers=headers,
)
response.raise_for_status()
print(response.json())
```

**Tip:** Create a reusable session so headers are sent on every request automatically:

```python
session = requests.Session()
session.headers.update(headers)

tenant = session.get("https://api.karbonhq.com/v3/TenantSettings").json()
contacts = session.get("https://api.karbonhq.com/v3/Contacts").json()
```

### C# (.NET)

```csharp
using System.Net.Http;
using System.Net.Http.Headers;

var token = Environment.GetEnvironmentVariable("KARBON_TOKEN");
var accessKey = Environment.GetEnvironmentVariable("KARBON_ACCESS_KEY");

using var client = new HttpClient { BaseAddress = new Uri("https://api.karbonhq.com/v3/") };
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
client.DefaultRequestHeaders.Add("AccessKey", accessKey);

var response = await client.GetAsync("TenantSettings");
response.EnsureSuccessStatusCode();

var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
```

**Tip:** Register `HttpClient` as a singleton (e.g., via `IHttpClientFactory` in ASP.NET Core) so
headers are configured once and reused across requests.

### Ruby (net/http)

```ruby
require 'net/http'
require 'uri'
require 'json'

uri = URI('https://api.karbonhq.com/v3/TenantSettings')

response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
  request = Net::HTTP::Get.new(uri)
  request['Authorization'] = "Bearer #{ENV['KARBON_TOKEN']}"
  request['AccessKey'] = ENV['KARBON_ACCESS_KEY']
  http.request(request)
end

puts JSON.parse(response.body)
```

## Verifying Your Setup

A successful `GET /v3/TenantSettings` returns your tenant's configuration:

```json
{
  "ContactTypes": [
    "Individual",
    "Business"
  ],
  "WorkTypes": [
    ...
  ],
  "WorkStatuses": [
    ...
  ],
  "ServiceTypes": [
    ...
  ],
  "ClientAccessActivated": false
}
```

Cache this response — you'll need `WorkTypes`, `ContactTypes`, and `WorkStatuses` throughout your
integration. Each entry in `ServiceTypes` lists the work types that make up that service, by key.

## Account-Level Access

The Karbon API operates at the **account level**, not the user level. When you authenticate, you are
acting on behalf of the entire Karbon account — not as any individual user within it.

This means:

- Actions taken via the API (creating work, updating contacts, recording payments) are not
  attributed to a specific Karbon user
- The `AccessKey` is tied to your API application and the account it's connected to, not to any
  individual's login
- All data visible within that account is accessible regardless of which user would normally see it
  in the Karbon UI

If your integration needs to attribute actions to a specific person (e.g., setting an assignee on a
work item), you pass that user's email address explicitly in the request body — it is not inferred
from the credentials.

## Common Authentication Errors

| Status             | Meaning                                                  |
| ------------------ | -------------------------------------------------------- |
| `401 Unauthorized` | Missing or invalid `Authorization` header or `AccessKey` |

## Rotating Your Access Key

Rotate your Access Key if you suspect it has been compromised, or as part of routine credential hygiene.

1. Go to **Settings → Connected Apps → API Applications**
2. Click **Manage** next to your application
3. Click **Rotate** next to the Access Key field
4. A confirmation dialog will appear — click **Rotate** to confirm

> **Warning:** Rotating your Access Key immediately invalidates the previous key. Any existing API requests using the old key will stop working until you update them with the new value. Make sure you are ready to update all integrations before confirming.

## Security Note

Never hard-code credentials in source code. Use environment variables or a secrets manager.
