OrangeQC Customer API
API Reference

Getting Started

Read-only HTTP/JSON access to your OrangeQC data. Built for BI tools (PowerBI, Tableau, Looker), AI agents, and custom integrations. Authenticate with an API key, paginate with page and per_page, get JSON back.

Overview

The Customer API gives you read-only programmatic access to your OrangeQC data. Anywhere you can make an HTTP request — a BI tool, an AI assistant, a Python notebook, a custom dashboard — you can pull live inspection data from your account. Common use cases:

  • BI dashboards and reporting. Pull inspection data into PowerBI, Tableau, Looker, or Google Data Studio and refresh on a schedule. No need to maintain a copy of your data in a separate warehouse.
  • AI agents and assistants. Connect Claude, ChatGPT, or an in-house LLM to your inspection history and ask questions in plain language.
  • Third-party integrations. Feed inspection data into ticketing systems, asset management tools, CRMs, or any other system your operations depends on.
  • Custom internal tools. Build operations command centers, executive scorecards, or one-off analytics scripts — in whatever stack your team already uses.

Everything is scoped to the user who issued the API key, with the same permissions they have in OrangeQC. There is nothing to install — generate an API key in Settings, paste it into your tool, and start pulling data.

Authentication

Customer API access is enabled per account by OrangeQC. Once enabled, any user in your account can generate their own API keys from Settings → API Keys.

  1. Go to Settings → API Keys in OrangeQC.
  2. Click Generate key, give it a memorable name (e.g. PowerBI, Claude, Internal dashboard).
  3. Copy the API key shown in the confirmation modal. This is the only time the plaintext key is visible — OrangeQC only stores a hash. If you lose it, generate a new one and delete the old key.
  4. Send the API key on every request as an Authorization: Bearer <api-key> header.

The API key's permissions track the issuing user. If the user is deactivated, their account stops paying, or the account's Customer API access is turned off, all keys belonging to that user start returning 401 or 403. Rotate keys by generating a new one, swapping it into your client, and deleting the old one.

Pagination & lookback

List endpoints are page-based. Responses include a meta object describing the page you just received:

{
  "inspections": [ ... ],
  "meta": {
    "page": 1,
    "per_page": 50,
    "total_pages": 12,
    "total_entries": 587
  }
}
  • page — 1-indexed. Default 1.
  • per_page — default 50, maximum 200. Values outside the range are clamped.
  • Lookback window: the API returns inspections from the past year. Older inspections are not returned even if you page past them.

Error envelope

Every error response follows the same shape. request_id correlates with our internal logs — include it when reporting issues.

{
  "error": {
    "code": "unauthorized",
    "message": "Invalid or missing API key",
    "request_id": "abc123-..."
  }
}
  • 401 unauthorized — missing or invalid API key, deactivated user, or expired account.
  • 403 forbidden — Customer API is not enabled for this account.
  • 404 not_found — resource does not exist (or you can't see it).
  • 429 too_many_requests — you've exceeded 600 requests per minute on this key. Honor the Retry-After header and back off.
  • 500 internal_error — server-side bug; the request_id is logged.

PowerBI example

Paste this into the PowerBI Desktop Advanced Editor when creating a new Blank Query. Replace YOUR_API_KEY_HERE with the API key you copied from OrangeQC. The query handles pagination automatically by walking until the API stops returning new pages.

let
    ApiKey      = "YOUR_API_KEY_HERE",
    BaseUrl     = "https://api.orangeqc.com/v1/inspections",
    PerPage     = 200,

    GetPage = (pageNumber as number) as record =>
        let
            Response = Json.Document(Web.Contents(
                BaseUrl,
                [
                    Query   = [ page = Text.From(pageNumber), per_page = Text.From(PerPage) ],
                    Headers = [ Authorization = "Bearer " & ApiKey, Accept = "application/json" ]
                ]
            ))
        in
            Response,

    FirstPage   = GetPage(1),
    TotalPages  = FirstPage[meta][total_pages],

    AllPages    = List.Generate(
                    () => [ page = 1, data = FirstPage[inspections] ],
                    each [page] <= TotalPages,
                    each [ page = [page] + 1, data = GetPage([page] + 1)[inspections] ],
                    each [data]
                  ),

    Combined    = List.Combine(AllPages),
    AsTable     = Table.FromList(Combined, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    Expanded    = Table.ExpandRecordColumn(AsTable, "Column1",
                    {"id","name","score","points","deficient","flagged","started_at","ended_at","structure_path"},
                    {"id","name","score","points","deficient","flagged","started_at","ended_at","structure_path"})
in
    Expanded

PowerBI gotchas to know about:

  • When prompted for credentials, choose Anonymous (the API key is in the header, not in PowerBI's credential store).
  • Set the data source Privacy Level to Organizational, otherwise PowerBI's Privacy Firewall will refuse to combine API data with other sources.
  • For PowerBI Service refresh, you'll need to add a gateway data source with Anonymous auth pointing at https://api.orangeqc.com.

curl example

Minimum viable request:

curl -sS https://api.orangeqc.com/v1/inspections \
  -H "Authorization: Bearer YOUR_API_KEY_HERE" \
  -H "Accept: application/json"

Paginated walk through every page using jq:

API_KEY="YOUR_API_KEY_HERE"
PAGE=1

while : ; do
  RESPONSE=$(curl -sS "https://api.orangeqc.com/v1/inspections?page=${PAGE}&per_page=200" \
    -H "Authorization: Bearer ${API_KEY}" \
    -H "Accept: application/json")

  echo "$RESPONSE" | jq -c '.inspections[]'

  TOTAL=$(echo "$RESPONSE" | jq '.meta.total_pages')
  [ "$PAGE" -ge "$TOTAL" ] && break
  PAGE=$((PAGE + 1))
done

Python example

Using the standard requests library. Drop-in for Jupyter, scripts, or an ETL job.

import requests

API_KEY  = "YOUR_API_KEY_HERE"
BASE_URL = "https://api.orangeqc.com/v1/inspections"
HEADERS  = {
    "Authorization": f"Bearer {API_KEY}",
    "Accept": "application/json",
}


def fetch_all_inspections(per_page: int = 200):
    page = 1
    while True:
        response = requests.get(
            BASE_URL,
            headers=HEADERS,
            params={"page": page, "per_page": per_page},
            timeout=30,
        )
        response.raise_for_status()
        body = response.json()

        yield from body["inspections"]

        if page >= body["meta"]["total_pages"]:
            break
        page += 1


if __name__ == "__main__":
    for inspection in fetch_all_inspections():
        print(inspection["id"], inspection["score"], inspection["name"])

For long-running clients, add retry logic on 429 (honor the Retry-After header) and on transient 5xx errors.

Try it live

The interactive reference lets you authorize with your API key, expand any endpoint, and send real requests against your OrangeQC account.

Open the API Reference