Documentation / Overview
REPAIRHQ PUBLIC API v1.0

Your shop data.
Your next connection.

Connect RepairHQ to the tools your business runs on. Start with secure, read-only access to repairs, inventory, customers, and events.

BASE URLhttps://www.repairhq.io/api/public/v1GET

Scoped to your store

Each token belongs to one business and one location.

Simple JSON responses

Four resources, explicit fields, and cursor pagination.

Signed event delivery

HMAC signatures and delivery IDs for reliable handling.

01 / GET STARTED

From token to first request

You’ll need a RepairHQ workspace and an owner or admin account to create a token.

  1. Choose the business and location

    Open your workspace, select the intended business and location, then go to More → API & integrations.

  2. Create a scoped token

    Under Scoped API access, enter an integration label, select the resources it needs, and choose an expiry from 1 to 90 days. Select Create scoped token and copy the returned token before closing it.

  3. Make a request from your server

    Store the token in a secret manager or server environment variable named REPAIRHQ_TOKEN. Pick a resource below and copy the request example.

Explore the request examples
Two different kinds of connection

BlockChyp, Stripe, and Square credentials connect payment providers to your shop. A RepairHQ API token lets your own integration read RepairHQ records. Payment-provider keys cannot authenticate to this API.

02 / AUTHENTICATION

One token. One location.

Send the token in the authorization header on every request. A token begins with rhq_ followed by 64 lowercase hexadecimal characters.

HTTP header
Authorization: Bearer <your-scoped-token>

Resource permissions

Select only the scopes your integration needs:

  • repairs:read
  • inventory:read
  • customers:read
  • events:read

Business isolation

The token determines both business and location. There is no business or location override parameter. Each new store creates its own tokens; each location needs its own token.

Keep tokens on your server. Do not put them in URLs, public browser code, screenshots, or source control. The token list shows only its last four characters. Revoke a token in API & integrations to stop future requests.

To rotate, create a replacement token, update your integration, verify a read, then revoke the old token. Expiry does not renew automatically. Webhook signing secrets are separate from API tokens.

03 / API REFERENCE

Read the records you need

One endpoint, four resources. All responses use application/json. These examples contain fictional data and run no requests from this page.

GET/api/public/v1?resource=repairs

Repairs

Repair tickets, their current status, priority, and due date.

Required scope repairs:read

Terminal
# Set REPAIRHQ_TOKEN securely in your local environment.
curl --fail-with-body --get \
  'https://www.repairhq.io/api/public/v1' \
  --data-urlencode 'resource=repairs' \
  --header "Authorization: Bearer $REPAIRHQ_TOKEN"
Sample response · synthetic data · no request is sent200 OK
JSON response
{
  "resource": "repairs",
  "data": [
    {
      "id": "11111111-1111-4111-8111-111111111111",
      "number": "1042",
      "device": "Sample laptop",
      "status": "In repair",
      "priority": "Normal",
      "due_at": "2026-11-02",
      "updated_at": "2026-10-27T14:30:00.000Z"
    }
  ],
  "next": null
}

Response fields

FieldTypeDescription
iduuidRepair ticket ID.
numberstring / integerTicket number. Accept a decimal string or integer; preserve large numbers as strings.
devicestringDevice description.
statusstringCurrent workflow status.
prioritystringTicket priority.
due_atstring / nullDue date, or null when unset.
updated_atdate-timeLast recorded update.
Current API scope

Version 1 supports list reads only. Invoice reads, staff/payroll access, payment processing, and create/update/delete operations are not public API endpoints. There is no record-by-ID endpoint or date filter. Use the workspace for those workflows.

04 / PAGINATION & LIMITS

Work through every page

Each response has resource, data, and next. A page contains up to 50 records. Send a non-null next value back as after with the same token and resource; stop when next is null.

ParameterMeaning
resourcerepairs, inventory, customers, or events. Defaults to repairs when omitted.
afterUUID cursor returned as next. Omit it for the first page.

Results are ordered by UUID, not by creation or update time. Pagination is not a frozen snapshot. New or changed records can be missed during an active traversal; restart from the beginning for a fresh reconciliation. Do not reuse an old final cursor as a change-feed watermark.

Pagination · Node.js
// Server-side Node.js. Start a new traversal without an after cursor.
let after = null;
do {
  const url = new URL('https://www.repairhq.io/api/public/v1');
  url.searchParams.set('resource', 'inventory');
  if (after) url.searchParams.set('after', after);
  const response = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.REPAIRHQ_TOKEN}` }
  });
  if (!response.ok) throw new Error(`RepairHQ HTTP ${response.status}`);
  const page = await response.json();
  for (const item of page.data) console.log(item.id, item.quantity);
  after = page.next;
  if (after) await new Promise(resolve => setTimeout(resolve, 1100));
} while (after);
50records per page
60requests / token / minute
90 daysmaximum token lifetime

The rate limit uses fixed minute windows and is shared by requests using the same token. Pace workers together. On 429, wait at least the Retry-After header (60 seconds), add jitter, and retry. The pagination snippet stops on errors so your application can apply its retry policy.

05 / ERRORS

Handle failures deliberately

Example error · HTTP 403
{ "error": "This token does not allow this resource" }
StatusWhat to do
400Fix the resource name or malformed after cursor.
401Check the bearer header, token expiry, and revocation status.
403Create a token with the required resource scope.
405Use GET. Writes are not supported; this response may have no JSON body.
429Wait for Retry-After, then retry with jitter.
500Retry with bounded exponential backoff. If it persists, report the time, endpoint, and status without credentials or customer data.

Check the HTTP status before parsing a success response. Error messages can change; branch on status codes. Failed reads never authorize a payment or a record update.

06 / SIGNED WEBHOOKS

Receive events from your shop

In API & integrations → Connected systems & webhooks, create a webhook endpoint with a public HTTPS destination and one event type. Then choose Activate / rotate signing key and save the returned secret securely.

Destinations must use standard HTTPS port 443 and resolve only to public internet addresses. Localhost, private addresses, URL credentials, fragments, and redirects are not supported. Each endpoint belongs to the selected business and location.

EventTrigger
repair.updatedA repair ticket’s status changes.
job.updatedA job activity event is recorded.
invoice.paidRecorded invoice totals meet the settlement condition after a payment-total change. Verify the invoice ledger before fulfillment; this is not a bank settlement confirmation.
customer.createdA customer record is created.
inventory.changedAn inventory item’s on-hand quantity changes.

Payload and delivery identity

The payload identifies the event and related record; it does not include the complete record. id is the event ID. X-RHQ-Delivery-ID identifies this endpoint’s delivery and stays the same on retries.

Webhook payload · synthetic example
{
  "id": "44444444-4444-4444-8444-444444444444",
  "type": "repair.updated",
  "createdAt": "2026-10-27T14:30:00.000Z",
  "businessId": "55555555-5555-4555-8555-555555555555",
  "locationId": "66666666-6666-4666-8666-666666666666",
  "recordId": "11111111-1111-4111-8111-111111111111",
  "action": "Repair status changed"
}

Verify the original bytes

The signature is v1= followed by the hex HMAC-SHA256 digest of this message, using the entire signing secret as the UTF-8 HMAC key:

Signed message
X-RHQ-Delivery-ID + '.' + X-RHQ-Timestamp + '.' + raw_request_body

X-RHQ-Timestamp is Unix time in seconds at delivery attempt time. Verify the signature with a constant-time comparison, require a recent timestamp, and deduplicate by delivery ID. Our Node.js helper accepts a five-minute clock window and compares the original request bytes before JSON parsing.

Verification helper usage · handler excerpt
import { verifyRepairHQWebhook } from './webhook-node.mjs';

// rawBody is the original Buffer collected by your HTTP handler.
const valid = verifyRepairHQWebhook({
  secret: process.env.REPAIRHQ_WEBHOOK_SECRET,
  rawBody,
  deliveryId: request.headers['x-rhq-delivery-id'],
  timestamp: request.headers['x-rhq-timestamp'],
  signature: request.headers['x-rhq-signature']
});
// Reject an invalid signature before parsing JSON.
// If valid, atomically deduplicate and durably queue the event
// before returning 2xx. The helper verifies; it does not store events.
Download the tested Node.js verifier

After verification, validate the expected business, location, and event type. Atomically store the delivery ID and event in a durable queue before returning 2xx. An already accepted delivery should also receive 2xx. The helper performs signature checks only; your receiver supplies durable storage and deduplication.

Timing, retries, and rotation

  • Any 2xx response is accepted. A non-2xx response or an 8-second timeout marks the attempt failed.
  • Failed deliveries become eligible again after 15 minutes, up to five total attempts. Each worker run handles at most five due deliveries.
  • Automatic processing currently runs once daily at 13:15 UTC. Owners and admins can use Retry due deliveries to process another due batch. Delivery is queued; it is not a real-time guarantee.
  • Retries can duplicate a delivery and events can arrive out of order. Use durable deduplication and reconcile current record state when needed.
  • Inspect delivery status and attempt counts in API & integrations. After five failed attempts, automatic retries stop.
  • Rotating immediately replaces the signing secret. Coordinate the receiver change and keep the previous secret briefly in your receiver for in-flight requests. New attempts use the current secret. Disable delivery when retiring an endpoint.
07 / TESTING

Connect with confidence

The examples above are an offline reference. There is no public sandbox endpoint or special test token. For live testing, use an authorized workspace and location containing only test data, with a short-lived token and minimal scopes.

  1. Confirm the correct business, location, scopes, and expiry in API & integrations.
  2. Read one page, then verify pagination and the end-of-list null cursor.
  3. Check a disallowed resource returns 403 and a revoked token returns 401.
  4. For webhooks, use your own public HTTPS receiver. Generate an ordinary test event in that location and process due deliveries.
  5. Verify signature rejection for a changed body or stale timestamp, and acknowledge a duplicate without processing it twice.
  6. Before enabling a production integration, confirm it cannot read another store’s records and that its logs redact credentials and customer data.
08 / TOOLS & DOWNLOADS

A head start for your integration

After importing into Postman, set token in your private local environment or vault. Keep credentials out of shared collections and exports. Enable the after parameter only when following a returned cursor.

09 / VERSION HISTORY

Built on a clear contract

v1.0.0

Developer documentation launch

Documented the existing scoped read API and signed webhooks. Added OpenAPI, Postman, and a Node.js verifier. Invalid query values now return 400, rate-limit responses include Retry-After, and repair due dates use a timezone-independent YYYY-MM-DD value.

The public endpoint is versioned as /api/public/v1. Ignore unknown response fields so additive changes do not break your integration. Future write APIs and additional resources will be documented when available.