Quickstart

This quickstart connects an application to a synthetic company that already exists in Fictix.

To connect many companies with one key, use the staging organization-key quickstart. The steps below remain the company-key path, supported in both production and staging.

To call a provider API from your own software, follow Connect your software and the provider first requests. Public catalog snapshots observed on October 28, 2026 report 60 entries in both environments: 59 marked available/selectable and one FCI execute preview that is not selectable. These catalog reports are not production request tests or a strict parity claim; the published first-request templates were tested in staging only.

Start in the frontend — create an account or sign in to projects — not by putting a management credential into a browser or a local shell history. The signed-in Console manages its own WorkOS bearer session; never copy that session token or forward it to an integration.

1. Create or open a company in the Console

Sign in, select an organization, then generate a company or open a project. When it is ready, open its Connect to your builder panel. That panel is the source of truth for the company slug, API origin, and the current project API key.

If you need a key, use Company settings → Company API keys. Copy the full key only once and save it in your server-side secret manager.

2. Set server-side environment variables

Use values from the Console's Connect panel. A production configuration looks like this:

export FICTIX_API_ORIGIN="https://api.fictix.ai"
export FICTIX_PROJECT_SLUG="replace_with_console_slug"
export FICTIX_PROJECT_API_KEY="replace_with_console_key"

For staging, use https://api-staging.fictix.ai and a staging project/key from the Console.

Never mix a production key with a staging origin or vice versa.

3. Confirm the company is reachable

GET/api/v1/orgs/{slug}/info
curl -sS \
  "$FICTIX_API_ORIGIN/api/v1/orgs/$FICTIX_PROJECT_SLUG/info" \
  -H "X-API-Key: $FICTIX_PROJECT_API_KEY" | jq

The response identifies the generated company and includes record-count metadata. A 401 or 403 usually means the key is missing, revoked, or belongs to a different project. Rotate or issue a replacement key in the Console rather than sharing a colleague's key.

4. Read company data

GET/api/v1/orgs/{slug}/data/customers

Fetch a small page first:

curl -sS \
  "$FICTIX_API_ORIGIN/api/v1/orgs/$FICTIX_PROJECT_SLUG/data/customers?limit=10" \
  -H "X-API-Key: $FICTIX_PROJECT_API_KEY" | jq

Use a bounded page size and continue until the returned count is satisfied. The same project key can read normalized data, export ledgers, and call supported native-shaped service routes.

5. Export a ledger

GET/api/v1/orgs/{slug}/export/invoices
curl -sS \
  "$FICTIX_API_ORIGIN/api/v1/orgs/$FICTIX_PROJECT_SLUG/export/invoices?format=csv" \
  -H "X-API-Key: $FICTIX_PROJECT_API_KEY" \
  -o invoices.csv

For a full runtime CSV pack, use the export-pack route documented in Runtime And Native Routes. For a portable partner loader, use the normalized /api/v1/demo-jobs entity exports only when your account has approved control-plane access.

6. Discover what Fictix supports

Catalog endpoints are public discovery endpoints; they contain no tenant data and do not require a project key:

GET/api/v1/catalog/entities
GET/api/v1/catalog/services
GET/api/v1/catalog/connector-capabilities
curl -sS "$FICTIX_API_ORIGIN/api/v1/catalog/entities" | jq
curl -sS "$FICTIX_API_ORIGIN/api/v1/catalog/services" | jq
curl -sS "$FICTIX_API_ORIGIN/api/v1/catalog/connector-capabilities" | jq

Read the catalog before assuming a particular native service/object combination is available. See Capability Matrix.

Minimal server-side loader

This Python example follows the count and offset fields in the entity-page response and collects every page. Install its dependency first:

python -m pip install requests
import os
import requests

ORIGIN = os.environ["FICTIX_API_ORIGIN"].rstrip("/")
SLUG = os.environ["FICTIX_PROJECT_SLUG"]
HEADERS = {"X-API-Key": os.environ["FICTIX_PROJECT_API_KEY"]}

def fetch_customers(page_size: int = 100) -> list[dict]:
    url = f"{ORIGIN}/api/v1/orgs/{SLUG}/data/customers"
    rows = []
    seen_ids = set()
    offset = 0
    total = None

    while total is None or offset < total:
        response = requests.get(
            url,
            headers=HEADERS,
            params={"limit": page_size, "offset": offset},
            timeout=30,
        )
        response.raise_for_status()
        page = response.json()
        data = page.get("data")
        count = page.get("count")

        if not isinstance(data, list) or type(count) is not int or count < 0:
            raise ValueError("Expected an entity page with data and a non-negative count")
        if "offset" in page and page["offset"] != offset:
            raise ValueError(f"Requested offset {offset}, received {page['offset']}")
        if len(data) > page_size:
            raise ValueError(f"Received {len(data)} rows for limit {page_size}")
        if total is not None and count != total:
            raise ValueError(f"Entity count changed during pagination: {total} to {count}")
        total = count

        for row in data:
            record_id = row.get("id") if isinstance(row, dict) else None
            if record_id is None or not str(record_id).strip():
                raise ValueError(f"Record at offset {offset} has no id")
            record_id = str(record_id)
            if record_id in seen_ids:
                raise ValueError(f"Duplicate record id across pages: {record_id}")
            seen_ids.add(record_id)
            rows.append(row)

        if not data and offset < total:
            raise ValueError(f"Pagination stopped at {offset} before count {total}")
        offset += len(data)

    if len(rows) != total:
        raise ValueError(f"Fetched {len(rows)} rows, but count is {total}")
    return rows

customers = fetch_customers()

For a complete runnable Node.js 24 server-side app with a local dashboard and a read-only verifier, download the customer integration example ZIP. It includes a placeholder .env.example and no credentials. Check the archive manifest for the included files and their SHA-256 hashes. Its optional native QBO write is an explicitly gated experiment: Fictix's public docs do not define that vendor request body, and connector fidelity and plan entitlement still apply.

Keep the key in your backend or worker environment. Do not run this request from browser code with the full key exposed.

Programmatic company creation

POST/api/v1/demo-jobs

For external callers, POST /api/v1/demo-jobs remains the normalized control-plane contract for approved server-to-server integrations. It requires the Fictix-supplied FICTIX_ADMIN_API_KEY / X-Admin-Key plus an Idempotency-Key. The signed-in Console uses its managed WorkOS bearer session instead; it is not the first step for a Console customer, and its session token must never be copied. Never use email/password auth.

See Demo Jobs when your Fictix account has that access.

Next steps