You are reading v0, which is retired on 2026-06-30. It is kept online for existing integrations only. Read the v1 version.

Quickstart

Create an API key, make your first authenticated call and read a paginated list in under five minutes.

Version v0 · updated 2026-02-01

Everything a Framique store holds — catalogue, orders, customers, exports, webhooks — is reachable over one versioned REST surface. This page takes you from an empty terminal to a real response.

1. Create an API key#

  1. Open the merchant admin and go to Settings → Developers.
  2. Create a key, choose the narrowest scopes the integration needs, and copy the secret. It is shown once and stored only as a hash.
  3. Keys are tenant-scoped: a key issued by one store can never read another store's data, whatever it asks for.

2. Make the first call#

Identity of the calling credential
curl -s "https://api.framique.com/api/public/v1/me" \
  -H "Authorization: Bearer $FRAMIQUE_API_KEY"
200 OK
{
  "merchant_id": "7f1c…",
  "name": "Nokshi Kotha",
  "scopes": ["orders.read", "products.read"],
  "rate_limit": { "limit": 600, "remaining": 599, "reset_at": "2026-02-01T09:00:00Z" }
}
GET/me

Read-only, against a demo store. Requires products.read on a real credential.

Same call as curl
curl -s -X GET "https://api.framique.com/api/public/v1/me" \
  -H "Authorization: Bearer $FRAMIQUE_API_KEY"

3. Read a paginated list#

Every list endpoint is cursor paginated. Never build page numbers: rows shift while you read them, and an offset silently skips or repeats orders. Follow `next_cursor` until it is null.

Walk every page without dropping a row
async function* allOrders(key: string) {
  let cursor: string | null = null;
  do {
    const url = new URL("https://api.framique.com/api/public/v1/orders");
    url.searchParams.set("limit", "100");
    if (cursor) url.searchParams.set("cursor", cursor);

    const res = await fetch(url, { headers: { Authorization: `Bearer ${key}` } });
    if (res.status === 429) {
      // Respect the reset header instead of hammering the bucket.
      const wait = Number(res.headers.get("retry-after") ?? 1);
      await new Promise((r) => setTimeout(r, wait * 1000));
      continue;
    }
    if (!res.ok) throw new Error(`orders ${res.status}`);

    const page = await res.json();
    yield* page.data;
    cursor = page.next_cursor;
  } while (cursor);
}
  • Authentication — API keys versus OAuth, and which one your integration wants.
  • Rate limits — the buckets, the headers and the backoff we expect.
  • Webhooks — how to be told about a change instead of polling for it.

Something wrong on this page? It is written in src/lib/docs-content.ts#quickstart tell us and we will fix it.