DailyAPI Documentationv1

Pagination

Traverse Daily collections safely with opaque, stable cursors.

View OpenAPI

Every collection uses cursor pagination. The initial request omits cursor; subsequent requests pass the exact page.next_cursor returned by the previous response.

Field or parameterBehavior
limitInteger from 1 to 100; default 50
cursorOpaque string, maximum 512 characters
page.has_moretrue when another page was observed
page.next_cursorNext cursor when has_more is true; otherwise null

Do not decode, edit, cache permanently, or reuse a cursor with a different resource. Malformed, mismatched, or invalid cursors return 400 invalid_filter.

Ordering and stability

Customers, suppliers, leads, products, documents, payments, inventory levels, and tasks are ordered by updated_at descending and then ID descending. Inventory movements are ordered by created_at descending and then ID descending. The cursor carries both ordering values, which prevents same-timestamp rows from being skipped within one traversal.

For repeatable synchronization, capture the synchronization start time before page 1 and persist a high-water mark only after every page succeeds. Because rows can change during traversal, downstream writes should be idempotent by resource ID.

cURL loop

set -euo pipefail
: "${DAILY_API_KEY:?DAILY_API_KEY is required}"

cursor=""
while :; do
  url='https://api.godaily.co.il/v1/customers?limit=100'
  if [ -n "$cursor" ]; then
    encoded_cursor="$(node -e 'process.stdout.write(encodeURIComponent(process.argv[1]))' "$cursor")"
    url="${url}&cursor=${encoded_cursor}"
  fi

  body="$(curl --fail-with-body --silent --show-error \
    --header "Authorization: Bearer ${DAILY_API_KEY}" \
    --header 'Accept: application/json' \
    "$url")"

  BODY="$body" node -e '
    const page = JSON.parse(process.env.BODY);
    for (const customer of page.data) console.log(customer.id, customer.name);
  '

  cursor="$(BODY="$body" node -e '
    const page = JSON.parse(process.env.BODY);
    process.stdout.write(page.page.next_cursor ?? "");
  ')"
  [ -n "$cursor" ] || break
done

TypeScript loop

type Page<T> = {
  data: T[];
  page: { has_more: boolean; next_cursor: string | null };
  request_id: string;
};

const apiKey = process.env.DAILY_API_KEY;
if (!apiKey) throw new Error('DAILY_API_KEY is required');

let cursor: string | null = null;
do {
  const url = new URL('https://api.godaily.co.il/v1/customers');
  url.searchParams.set('limit', '100');
  if (cursor) url.searchParams.set('cursor', cursor);

  const response = await fetch(url, {
    headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}` },
  });
  const body = await response.json() as Page<{ id: string; name: string }> & {
    error?: { code: string };
  };
  if (!response.ok) {
    throw new Error(`Daily API ${response.status} (${body.request_id}): ${body.error?.code ?? 'unknown_error'}`);
  }

  for (const customer of body.data) console.log(customer.id, customer.name);
  cursor = body.page.next_cursor;
} while (cursor);

Python loop

import os
import requests

api_key = os.environ.get("DAILY_API_KEY")
if not api_key:
    raise RuntimeError("DAILY_API_KEY is required")

cursor = None
with requests.Session() as session:
    session.headers.update({"Accept": "application/json", "Authorization": f"Bearer {api_key}"})
    while True:
        params = {"limit": 100}
        if cursor:
            params["cursor"] = cursor
        response = session.get(
            "https://api.godaily.co.il/v1/customers",
            params=params,
            timeout=30,
        )
        body = response.json()
        if not response.ok:
            code = body.get("error", {}).get("code", "unknown_error")
            raise RuntimeError(f"Daily API {response.status_code} ({body.get('request_id')}): {code}")
        for customer in body["data"]:
            print(customer["id"], customer["name"])
        cursor = body["page"]["next_cursor"]
        if not cursor:
            break

Each page is a separate request and counts toward rate limits. Apply 429 retry handling around the page request rather than restarting the entire traversal.

On this page