Home

Making Your First API Request

The Karbon API uses two required headers on every 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:

HeaderFormatWhere to find it
AuthorizationBearer {token}Issued when you register for API access
AccessKeyJWT (starts with eyJ...)Karbon UI → Settings → Connected Apps → your application

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 and Bruno 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>
  1. 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

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

JavaScript (fetch)

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)

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)

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:

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)

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)

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)

Or with the faraday gem for a cleaner interface:

require 'faraday'
require 'json'

conn = Faraday.new(url: 'https://api.karbonhq.com/v3') do |f|
  f.headers['Authorization'] = "Bearer #{ENV['KARBON_TOKEN']}"
  f.headers['AccessKey'] = ENV['KARBON_ACCESS_KEY']
  f.response :raise_error
end

response = conn.get('/TenantSettings')
puts JSON.parse(response.body)

Verifying Your Setup

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

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

Cache this response — you’ll need WorkTypes, ContactTypes, and WorkStatuses throughout your integration.

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

StatusMeaning
401 UnauthorizedMissing or invalid Authorization header or AccessKey

Security Note

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