APIXX.flow logo
Back to app
API Reference · v1

APIXX REST API

REST endpoints for programmatic access to your flows, runs, connectors, and canonical data. All requests use JSON and respect the same permissions as your APIXX account. For AI-assistant access to the same data, see the MCP Server.

Base URL
https://app.apixx.io/v1

Authentication

All requests require a bearer token. Generate keys from the Settings → API keys page. Keys are scoped to your customer and inherit the roles of the user that created them. Each key has explicit scopes (e.g. flows:read, runs:read, data:read) — request only what you need.

Authorization: Bearer apixx_••••••••
Content-Type: application/json
  • Keys are prefixed apixx_ and shown once at creation — copy and store them in your secret manager immediately.
  • Treat keys like passwords — never embed them in client-side or mobile code.
  • Rotate by creating a new key, switching your caller, then revoking the old one.
  • Set an expiry (30/90/365 days) for short-lived integrations and CI tokens.

Quickstart

# 1. Create a key in Settings → API keys (scope: flows:read, runs:read)
export APIXX_KEY="apixx_••••••••"

# 2. List your flows
curl https://app.apixx.io/v1/flows -H "Authorization: Bearer $APIXX_KEY"

Endpoints

Flows

GET/flowsList all flows for the current customer.
GET/flows/:idRetrieve a single flow with connector + schedule details.
POST/flows/:id/pausePause a flow. Returns the updated flow.
POST/flows/:id/resumeResume a paused flow.
POST/flows/:id/triggerManually trigger a run. Returns the new run id.

Runs

GET/runsList runs. Filter via ?flow_id=, ?status=, ?from=, ?to=.
GET/runs/:idRetrieve a run with records processed, duration, and errors.
POST/runs/:id/retryRetry a failed run. Returns the new run id.

Connectors

GET/connectorsList connected systems and their current status.
GET/connectors/:idRetrieve a single connector.
POST/connectors/:id/verifyTest the credentialed link. Returns ok / error.

APIXX Data — Canonical Read API

Pull normalized, deduplicated records from the canonical data layer. Endpoints are scoped to the API key's tenant and require the data:read scope. The base path is https://app.apixx.io/api/public/data.

GET/api/public/data/:entityList canonical records. Supports ?limit, ?cursor, ?updated_since, ?fields.
GET/api/public/data/:entity/:idRetrieve a single canonical record by canonical_id.

:entitycustomer, contact, account, lead, opportunity, product, product_variant, order, order_line_item, invoice, payment, subscription, refund, shipment, inventory.

curl 'https://app.apixx.io/api/public/data/order?limit=50&updated_since=2026-06-01T00:00:00Z' \
  -H "Authorization: Bearer apixx_••••••••"
{
  "entity": "order",
  "count": 50,
  "next_cursor": "2026-06-12T18:21:04.512Z",
  "data": [
    {
      "canonical_id": "5f0d3a7e-2c6b-4f31-9c3d-1a4e5b6c7d80",
      "order_number": "1042",
      "status": "paid",
      "total_cents": 12450,
      "currency": "USD",
      "placed_at": "2026-06-12T18:20:11Z",
      "external_ids": { "shopify": "gid://shopify/Order/1042" },
      "last_source_update_at": "2026-06-12T18:21:04Z",
      "updated_at": "2026-06-12T18:21:04.512Z"
    }
  ]
}

Paginate by passing the response's next_cursor as the next request's ?cursor. When next_cursor is null you've reached the end of the result set.

Example request

curl https://app.apixx.io/v1/flows \
  -H "Authorization: Bearer apixx_••••••••"
{
  "data": [
    {
      "id": "flw_8sJk2",
      "name": "Shopify → NetSuite Orders",
      "status": "active",
      "source": "shopify",
      "destination": "netsuite",
      "schedule": "every_15m",
      "last_run_at": "2026-06-10T19:42:11Z"
    }
  ],
  "meta": { "total": 1, "has_more": false }
}

Webhooks

Subscribe to events to receive HTTP callbacks instead of polling. Configure endpoints under Settings → Webhooks. APIXX sends a POST with a JSON body and these headers:

X-Apixx-Event: run.failed
X-Apixx-Delivery: del_4nQ2k
X-Apixx-Signature: t=1781119222,v1=8f4a2c...

Events

run.startedFired when a run begins.
run.succeededFired when a run completes with zero record errors.
run.partialCompleted, but some records failed.
run.failedRun aborted before completing.
connector.degradedA connector started returning auth or quota errors.
flow.pausedA flow was paused via API or UI.

Signature verification

Compute HMAC-SHA256(secret, timestamp + "." + raw_body) and compare using a timing-safe equality check. Reject deliveries older than 5 minutes.

import { createHmac, timingSafeEqual } from "crypto";

function verify(req, secret) {
  const header = req.headers["x-apixx-signature"];
  const [tPart, sigPart] = header.split(",");
  const timestamp = tPart.slice(2);
  const signature = sigPart.slice(3);

  const expected = createHmac("sha256", secret)
    .update(timestamp + "." + req.rawBody)
    .digest("hex");

  return timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
}

Retries

Non-2xx responses are retried with exponential backoff for up to 24 hours. Return 2xx as soon as the payload is persisted; do downstream work asynchronously.

Pagination

List endpoints are cursor-paginated. Pass ?limit= (default 50, max 500) and ?cursor= from the previous response. When next_cursor is null, you've reached the end.

let cursor: string | null = null;
do {
  const url = new URL("https://app.apixx.io/v1/runs");
  url.searchParams.set("limit", "200");
  if (cursor) url.searchParams.set("cursor", cursor);
  const res = await fetch(url, {
    headers: { Authorization: `Bearer ${process.env.APIXX_KEY}` },
  });
  const { data, meta } = await res.json();
  for (const run of data) process(run);
  cursor = meta.next_cursor;
} while (cursor);

For incremental sync, use ?updated_since=<ISO-8601> instead of paging the whole table. Store the highest updated_at you've seen and pass it next run.

Idempotency

All POST endpoints accept an Idempotency-Key header (any unique string per logical request, e.g. a UUID). Replays within 24 hours return the original response without re-executing the operation — safe to retry on network failures.

curl -X POST https://app.apixx.io/v1/flows/flw_8sJk2/trigger \
  -H "Authorization: Bearer $APIXX_KEY" \
  -H "Idempotency-Key: 7f2c1d4a-9b3e-4e6a-8d2f-12ab34cd56ef"

Rate limits

The API uses a sliding-window limiter per API key:

Read endpointsGET600 requests / minute
Write endpointsPOST · PATCH · DELETE120 requests / minute
Trigger endpointsPOST /flows/:id/trigger60 requests / minute

Every response includes:

X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 1781119282

Exceeding the limit returns 429 Too Many Requests with a Retry-After header (seconds).

Errors

Errors use standard HTTP status codes and a consistent JSON body:

{
  "error": {
    "code": "flow_not_found",
    "message": "No flow with id 'flw_xyz'.",
    "request_id": "req_2k9Lz"
  }
}
400invalid_requestMalformed JSON or missing required field.
401unauthorizedMissing or invalid bearer token.
403forbiddenToken lacks permission for this resource.
404not_foundResource does not exist or is not visible to you.
409conflictResource is in a state that conflicts with the request.
422validation_errorInput failed validation. See `message`.
429rate_limitedToo many requests. Honor `Retry-After`.
5xxinternal_errorTransient — safe to retry with backoff.

Always log the request_id — APIXX support can use it to trace your call end-to-end.

Versioning

The current stable version is v1, encoded in the URL path. Breaking changes ship under a new major version with at least 6 months of overlap. Additive changes (new fields, new endpoints) may roll out under v1 at any time — design clients to ignore unknown fields.