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.
https://app.apixx.io/v1Authentication
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 | /flows | List all flows for the current customer. |
| GET | /flows/:id | Retrieve a single flow with connector + schedule details. |
| POST | /flows/:id/pause | Pause a flow. Returns the updated flow. |
| POST | /flows/:id/resume | Resume a paused flow. |
| POST | /flows/:id/trigger | Manually trigger a run. Returns the new run id. |
Runs
| GET | /runs | List runs. Filter via ?flow_id=, ?status=, ?from=, ?to=. |
| GET | /runs/:id | Retrieve a run with records processed, duration, and errors. |
| POST | /runs/:id/retry | Retry a failed run. Returns the new run id. |
Connectors
| GET | /connectors | List connected systems and their current status. |
| GET | /connectors/:id | Retrieve a single connector. |
| POST | /connectors/:id/verify | Test 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/:entity | List canonical records. Supports ?limit, ?cursor, ?updated_since, ?fields. |
| GET | /api/public/data/:entity/:id | Retrieve a single canonical record by canonical_id. |
:entity ∈ customer, 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.started | — | Fired when a run begins. |
| run.succeeded | — | Fired when a run completes with zero record errors. |
| run.partial | — | Completed, but some records failed. |
| run.failed | — | Run aborted before completing. |
| connector.degraded | — | A connector started returning auth or quota errors. |
| flow.paused | — | A 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 endpoints | GET | 600 requests / minute |
| Write endpoints | POST · PATCH · DELETE | 120 requests / minute |
| Trigger endpoints | POST /flows/:id/trigger | 60 requests / minute |
Every response includes:
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 587
X-RateLimit-Reset: 1781119282Exceeding 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"
}
}| 400 | invalid_request | Malformed JSON or missing required field. |
| 401 | unauthorized | Missing or invalid bearer token. |
| 403 | forbidden | Token lacks permission for this resource. |
| 404 | not_found | Resource does not exist or is not visible to you. |
| 409 | conflict | Resource is in a state that conflicts with the request. |
| 422 | validation_error | Input failed validation. See `message`. |
| 429 | rate_limited | Too many requests. Honor `Retry-After`. |
| 5xx | internal_error | Transient — 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.
