REST API reference

Sites and account

Export
Download Markdown Use with AI

Three endpoints tell your integration what it is connected to: GET /v1 checks that a credential works, GET /v1/sites lists the help centers it can act on, and GET /v1/account returns the account, the plan and what the credential may do. Call them when you connect a new API key or OAuth token, before you touch any content.

Endpoints

Method and path

What it does

Scope

GET /v1

Checks that a credential is valid

Any valid credential

GET /v1/sites

Lists the help centers the credential can act on

content.read

GET /v1/account

Returns the account, plan and capabilities behind the credential

Any valid credential

Every API key holds content.read, so all three work with any key. An OAuth token without content.read can call GET /v1 and GET /v1/account, and gets 403 Forbidden with "code": "insufficient_scope" from GET /v1/sites. See Scopes.

Check a credential

GET/v1

Check that an API key or OAuth token is valid.

A 200 OK means the key or token is valid. The banner needs no scope, so a Read only key and a Read & write key get the same answer. To find out what a credential may do, call GET /v1/account (below) and read kb.capabilities.

Every /v1 endpoint that takes a key or token answers 401 Unauthorized with {"status": "unauthorized"} when the apikey header is missing, when the key is mistyped or deleted, when the person who created the key no longer has a HelpCenter.io account, and when an OAuth token is expired, revoked or malformed. The body never says which of these it was.

The API's root, https://api.helpcenter.io/, answers the same message with no credential at all. A 200 from it proves nothing about your key, so always check /v1.

The site object

A help center, as GET /v1/sites returns it:

Field

Type

Description

id

integer

The help center's id. With an OAuth token, send it in the X-HCio-Site header to choose the help center a request acts on.

uuid

string

A stable public identifier. Export pages and webhook deliveries carry the same value as helpcenter_id.

name

string

The help center's name.

subdomain

string

The name in its <subdomain>.helpcenter.io address.

domain

string

Where readers find it: the custom domain when one is live, otherwise <subdomain>.helpcenter.io.

url

string

https:// followed by domain.

default_language

string

The default language code, for example en.

visibility

string

public, private or password, as set under Control who can see your help center.

publicly_accessible

boolean

true when anyone can open the help center: it is public, it is not suspended, and it has no IP allow-list.

languages

array of strings

The default language first, then every additional language. These are the keys the API accepts in per-language maps such as an article's title.

created_at

string

When the help center was created, in UTC, as YYYY-MM-DD HH:MM:SS.

List help centers

GET/v1/sites

List the help centers this credential can act on.

What you get depends on the credential:

  • An API key belongs to one help center, so the list holds exactly that one. The X-HCio-Site header and the site query parameter are ignored for API keys.

  • An OAuth token sees only the help centers that meet both conditions: the HelpCenter.io account of the person who approved your app owns them, and the person shared them with your app, on the consent screen or later in Connected Apps. The API checks both on every request, so a change shows in the list on your next request. Use each id in X-HCio-Site, as described in Choose which help center a request acts on.

The list is ordered by id and has no pages: meta.items_count is its length.

Get the account

GET/v1/account

Get the account, plan and capabilities behind this credential.

The response has three blocks:

Field

Type

Description

account

object

The HelpCenter.io account the credential acts for: id, email and name of the account's owner. For an API key, this is the account of the person who created the key. If they were invited to the help center from another HelpCenter.io account, you see their own account, not the one that owns the help center.

provider

string

Always helpcenter.io.

plan

object

The account's plan. See the next table.

kb.sites_count

integer

How many help centers this credential can act on.

kb.site_ids

array of integers

Their ids, the same ones GET /v1/sites lists.

kb.capabilities.read

boolean

true when the credential holds content.read.

kb.capabilities.write

boolean

true when it holds content.write. A Read only key reports false.

The plan block:

Field

Type

Description

name

string

The plan's identifier, for example catalyst_annual.

title

string

The plan's display title, or its name when it has none.

active

boolean

true when the account pays for its plan. An account in its free trial without a subscription reports false, with on_trial: true.

on_trial

boolean

true during the free trial.

ai_included

boolean

true when the plan includes the AI features.

specs

object

Feature flags of the plan, such as sso and staged_changes. A plan without flags returns [].

source

string

Where the active plan comes from: subscription, chat_bundle, both or none.

via_bundle, bundle

boolean, object or null

via_bundle is true when a bundle provides the plan, alone or with a subscription, and bundle then holds its details or null. Otherwise false and null.

Read kb.capabilities.write before your integration offers to create or change content, so a Read only key gets a clear message instead of a 403 halfway through a job.

This script prints the help centers a key reaches and whether it can write:

// Check which help centers a key reaches and whether it can write.
const API = 'https://api.helpcenter.io/v1';
const headers = { apikey: process.env.HELPCENTER_API_KEY, Accept: 'application/json' };

async function get(path) {
  const res = await fetch(API + path, { headers });
  if (!res.ok) throw new Error(`${path}: HTTP ${res.status}`);
  return res.json();
}

async function main() {
  const account = await get('/account');
  const { sites } = await get('/sites');
  for (const site of sites) {
    console.log(`${site.name} (${site.url}), languages: ${site.languages.join(', ')}`);
  }
  const canWrite = account.kb.capabilities.write;
  console.log(canWrite
    ? 'This key can create and change content.'
    : 'This key can only read.');
}

main().catch((err) => {
  console.error(err);
  process.exit(1);
});
# Check which help centers a key reaches and whether it can write.
import json
import os
import urllib.request

API = "https://api.helpcenter.io/v1"
HEADERS = {"apikey": os.environ["HELPCENTER_API_KEY"], "Accept": "application/json"}


def get(path):
    request = urllib.request.Request(API + path, headers=HEADERS)
    with urllib.request.urlopen(request) as response:
        return json.load(response)


account = get("/account")
for site in get("/sites")["sites"]:
    print(f"{site['name']} ({site['url']}), languages: {', '.join(site['languages'])}")
if account["kb"]["capabilities"]["write"]:
    print("This key can create and change content.")
else:
    print("This key can only read.")
<?php
// Check which help centers a key reaches and whether it can write.
$api = 'https://api.helpcenter.io/v1';
$headers = ['apikey: ' . getenv('HELPCENTER_API_KEY'), 'Accept: application/json'];

function get(string $url, array $headers): array
{
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_HTTPHEADER => $headers,
    ]);
    $body = curl_exec($ch);
    $status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
    if ($status !== 200) {
        throw new RuntimeException("$url: HTTP $status");
    }
    return json_decode($body, true);
}

$account = get("$api/account", $headers);
foreach (get("$api/sites", $headers)['sites'] as $site) {
    $languages = implode(', ', $site['languages']);
    echo "{$site['name']} ({$site['url']}), languages: $languages\n";
}
echo $account['kb']['capabilities']['write']
    ? "This key can create and change content.\n"
    : "This key can only read.\n";

For the Acme help center in the examples on this page and a Read & write key, it prints Acme (https://acme.helpcenter.io), languages: en, de and This key can create and change content.

Was this article helpful?