# Daily Public API — complete developer documentation > Canonical origin: https://docs.godaily.co.il > OpenAPI 3.1: https://docs.godaily.co.il/openapi.json # Authentication Canonical page: https://docs.godaily.co.il/docs/authentication Every request requires an API key in the HTTP `Authorization` header: ```http Authorization: Bearer $DAILY_API_KEY ``` The scheme and `Bearer` prefix are case-sensitive. Do not add spaces inside the key. ## Business-scoped keys A key is permanently associated with one Daily business. Daily derives business scope from the authenticated key; the client cannot select or override a business ID. A valid resource ID belonging to another business returns the same `resource_not_found` response as a missing resource. ## Environments Daily keys include an environment marker. Production accepts live keys and non-production environments accept test keys. A key for the wrong environment is rejected before credential lookup with `invalid_api_key`. ## One-time visibility and storage The complete key is shown once after creation or rotation. Daily stores a SHA-256 hash used for constant-time comparison, plus a non-secret public identifier and last four characters for management. The full secret cannot be recovered later. Your integration should store the key in an encrypted secret manager or an equivalently protected environment-injection system. Never embed it in frontend or mobile code: users, browser extensions, source maps, and device backups can extract shipped secrets. ## Expiration and subscription access Keys are created with a configured expiration. After that timestamp the API returns `401 expired_api_key`. Public API access also requires an active eligible Daily subscription and an active business. If access becomes unavailable, valid keys remain stored but requests return `403 api_access_inactive` until access is restored. ## Rotation Rotation creates a new secret for the same key identity. The old secret remains valid for 24 hours. 1. Rotate in [Daily → API keys](https://app.godaily.co.il/api-keys). 2. Save the new secret in your secret manager. 3. Deploy and verify the new secret. 4. Remove the old secret from every environment before the grace period ends. Never rely on the grace period as a permanent fallback. ## Revocation Revocation is immediate and irreversible. Requests using a revoked key return `401 revoked_api_key`. Revoke keys when an integration is retired, ownership changes, or exposure is suspected. ## IP and CIDR restrictions An optional allowlist can contain up to 20 IPv4, IPv6, or CIDR entries. When configured, requests are accepted only when the client address observed by Daily matches an entry. A mismatch returns `403 ip_not_allowed`. Keep outbound NAT changes synchronized with the allowlist. ## Browser use Production integrations must call Daily from a trusted server. The documentation playground is for controlled testing only: the entered key stays in current-page React memory, is cleared on refresh, and is sent directly from `https://docs.godaily.co.il` to the public API. --- # Changelog Canonical page: https://docs.godaily.co.il/docs/changelog ## 2026-08-18 ### Public API v1 introduced Repository commit `192ef16` (`feat: add read-only public API infrastructure`) introduced: - Business-scoped bearer API keys with one-time secret display, expiration, rotation grace, revocation, permissions, and IP allowlists - Read-only `/v1` operations for business, customers, suppliers, leads, products, documents and PDFs, payments, inventory and movements, and tasks - Cursor pagination, time/status/search filters, request IDs, safe public errors, and no-store responses - Nginx per-key and per-IP rate limits and sanitized public API access logging - API-key management and system-admin emergency revocation controls ### Deployment correction Repository commit `0e59c81` (`fix: unblock dev deployment pipeline`) adjusted deployment handling related to the new public API infrastructure. It did not add a new public endpoint or response contract. ### API-key navigation Repository commit `f6522b3` (`feat: move API keys to settings navigation`) moved API-key management to the dedicated `/api-keys` application route. It did not change the public `/v1` contract. This changelog contains only verified repository history. It does not infer earlier public releases. --- # Use the docs with a coding model Canonical page: https://docs.godaily.co.il/docs/coding-models Use the machine-readable assets published at the documentation origin: - [`llms.txt`](https://docs.godaily.co.il/llms.txt) — concise navigation index - [`llms-full.txt`](https://docs.godaily.co.il/llms-full.txt) — complete authored documentation - [`openapi.json`](https://docs.godaily.co.il/openapi.json) — OpenAPI 3.1 JSON - [`openapi.yaml`](https://docs.godaily.co.il/openapi.yaml) — OpenAPI 3.1 YAML - Clean page Markdown under `https://docs.godaily.co.il/markdown/` ## Recommended prompt context Tell the model to use the OpenAPI contract as the endpoint and schema authority, and `llms-full.txt` for operational guidance. Ask it to: 1. Read `DAILY_API_KEY` from the environment. 2. Fail clearly when the variable is missing. 3. call only `https://api.godaily.co.il/v1` with `GET`. 4. check HTTP status and parse the documented envelopes. 5. paginate until `next_cursor` is `null`. 6. honor `Retry-After` on 429 and 503. 7. redact credentials and signed PDF URLs. > Never paste an API key into a model prompt or attach production responses containing customer data. Give the model documentation, not credentials. --- # Errors Canonical page: https://docs.godaily.co.il/docs/errors All public API errors use the same JSON shape: ```json { "error": { "type": "authentication_error", "code": "invalid_api_key", "message": "A valid API key is required." }, "request_id": "req_docserrors001" } ``` Use HTTP status and `error.code` for program logic. Treat `message` as safe display text, not a stable parser interface. Record `request_id` without Authorization data. ## Public error catalog | Status | Type | Code | Message / cause | Recommended action | | --- | --- | --- | --- | --- | | 401 | `authentication_error` | `missing_api_key` | A valid API key is required. | Configure the Authorization header; do not retry unchanged. | | 401 | `authentication_error` | `invalid_api_key` | Missing format match, wrong environment, unknown key, or wrong secret. | Replace the configured secret. | | 401 | `authentication_error` | `expired_api_key` | The API key is no longer active. | Create or rotate to a valid key. | | 401 | `authentication_error` | `revoked_api_key` | The API key is no longer active. | Replace the revoked key. | | 403 | `authorization_error` | `insufficient_permission` | The key cannot access the resource. | Add the required permission or use the correct key. | | 403 | `authorization_error` | `api_access_inactive` | Public API access is unavailable for this subscription. | Restore eligible Daily subscription access. | | 403 | `authorization_error` | `ip_not_allowed` | Current source IP is not permitted. | Update the key allowlist or route from an approved address. | | 400 | `invalid_request_error` | `invalid_filter` | Invalid query, cursor, UUID, unsupported filter, unknown parameter, or oversized query. | Correct the request; do not retry unchanged. | | 404 | `not_found_error` | `resource_not_found` | Resource or route not found in the authenticated scope. | Stop or reconcile the local reference. | | 405 | `invalid_request_error` | `method_not_allowed` | Only GET and HEAD are supported. | Change the method. | | 429 | `rate_limit_error` | `rate_limit_exceeded` | Too many requests. | Honor `Retry-After: 1` and back off with jitter. | | 500 | `api_error` | `internal_error` | An internal error occurred. | Retry with backoff if safe; escalate with request ID. | | 503 | `api_error` | `service_unavailable` | The API is temporarily unavailable. | Honor `Retry-After: 5` and retry with backoff. | Validation failures intentionally do not expose internal field-validator details. Database and unexpected failures intentionally return a generic message. ## Safe client pattern ```python import os import requests api_key = os.environ.get("DAILY_API_KEY") if not api_key: raise RuntimeError("DAILY_API_KEY is required") response = requests.get( "https://api.godaily.co.il/v1/products", headers={"Accept": "application/json", "Authorization": f"Bearer {api_key}"}, timeout=30, ) body = response.json() if not response.ok: error = body.get("error", {}) request_id = body.get("request_id", response.headers.get("X-Request-ID", "not-returned")) code = error.get("code", "unknown_error") if response.status_code in (429, 503): retry_after = response.headers.get("Retry-After") raise RuntimeError(f"Transient Daily API error {code}; retry after {retry_after}s; request {request_id}") raise RuntimeError(f"Daily API error {code}; request {request_id}") ``` Never include the API key, complete request headers, or a signed PDF URL in error telemetry. --- # Filtering and sorting Canonical page: https://docs.godaily.co.il/docs/filtering-sorting Collection endpoints accept a defined subset of these parameters. Unknown parameters, unsupported combinations, invalid status values, and oversized values return `400 invalid_filter`. ## Common parameters | Parameter | Format | Default / constraint | Semantics | | --- | --- | --- | --- | | `limit` | integer | Default 50; minimum 1; maximum 100 | Maximum objects in this page. | | `cursor` | string | Maximum 512 characters | Opaque cursor from the same collection. | | `created_after` | strict ISO 8601 timestamp | Optional | Creation time strictly greater than the value. | | `updated_after` | strict ISO 8601 timestamp | Optional except inventory movements | Update time strictly greater than the value. | | `status` | resource enum | Maximum raw length 50 | Exact public status, case-insensitive. | | `search` | string | Trimmed; maximum 100 characters | Case-insensitive search over documented fields. | ## Resource matrix | Resource | Status values | Search fields | Time filters | Sort order | | --- | --- | --- | --- | --- | | Customers | `active`, `inactive` | name, business number, email, contact person | created, updated | `updated_at desc`, ID desc | | Suppliers | `active`, `inactive` | name, business number, email, contact person | created, updated | `updated_at desc`, ID desc | | Leads | `new`, `contacted`, `in_progress`, `proposal`, `negotiation`, `won`, `lost` | name, contact name, email, phone | created, updated | `updated_at desc`, ID desc | | Products | `active`, `inactive` | name, SKU, barcode | created, updated | `updated_at desc`, ID desc | | Documents | `open`, `converted`, `pending_payment`, `closed`, `credited`, `returned`, `partially_paid`, `partially_credited`, `partially_returned` | title, customer-name snapshot | created, updated | `updated_at desc`, ID desc | | Payments | `recorded` | Not supported | created, updated | `updated_at desc`, ID desc | | Inventory levels | `active`, `inactive` | product name | created, updated | `updated_at desc`, ID desc | | Inventory movements | `increase`, `decrease` | Not supported | created only | `created_at desc`, ID desc | | Tasks | `open`, `completed`, `canceled` | task title | created, updated | `updated_at desc`, ID desc | The business endpoint and single-resource endpoints accept no query parameters. ## Combining filters Filters are combined with logical AND. Search matches any of the listed search fields; time and status constraints still apply. ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" curl --fail-with-body --silent --show-error \ --get 'https://api.godaily.co.il/v1/documents' \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ --data-urlencode 'status=pending_payment' \ --data-urlencode 'updated_after=2026-07-01T00:00:00.000Z' \ --data-urlencode 'search=Orion' \ --data-urlencode 'limit=100' ``` ## Incremental retrieval Resources with `updated_after` support incremental reads. Store a UTC high-water timestamp taken before the traversal, request `updated_after` with overlap, fully paginate, and upsert by ID. The filter is exclusive, so overlap protects against clock and boundary mistakes; idempotent upserts remove duplicates. Inventory movements have no update timestamp and reject `updated_after`. Increment them using `created_after`, understanding that it tracks creation only. If your correctness model must detect historical change outside that contract, perform periodic full pagination. --- # Getting started Canonical page: https://docs.godaily.co.il/docs/getting-started This guide uses `GET /business`, a low-risk endpoint that returns identity and contact data for the business already bound to the API key. ## 1. Create an API key Open [Daily → API keys](https://app.godaily.co.il/api-keys). Only the primary business owner can manage keys. 1. Select **יצירת מפתח חדש**. 2. Give the key a name that identifies one integration. 3. Select the **פרטי העסק** permission. 4. Choose an expiration period. 5. Optionally restrict the key to trusted IPv4, IPv6, or CIDR ranges. 6. Create the key and copy it immediately. The complete secret is displayed once. Daily stores a one-way hash for later authentication, not a retrievable copy of the secret. ## 2. Store the key For local development, export the key in the active shell without committing it to a file: ```bash read -rsp "Daily API key: " DAILY_API_KEY && echo export DAILY_API_KEY ``` In production, inject `DAILY_API_KEY` from an encrypted secret manager. Grant access only to the workload that calls Daily. ## 3. Make the first request ### cURL ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" response_file="$(mktemp)" trap 'rm -f "$response_file"' EXIT status="$(curl --silent --show-error \ --output "$response_file" \ --write-out '%{http_code}' \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ 'https://api.godaily.co.il/v1/business')" if [ "$status" -lt 200 ] || [ "$status" -ge 300 ]; then printf 'Daily API request failed with HTTP %s\n' "$status" >&2 sed 's/daily_\(live\|test\)_[A-Za-z0-9_-]*/[redacted-api-key]/g' "$response_file" >&2 exit 1 fi cat "$response_file" ``` ### TypeScript with native `fetch` ```ts const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); const response = await fetch('https://api.godaily.co.il/v1/business', { method: 'GET', headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}`, }, }); const body = await response.json() as { data?: { id: string; name: string }; error?: { code: string; message: string }; request_id: string; }; if (!response.ok || !body.data) { throw new Error(`Daily API ${response.status} (${body.request_id}): ${body.error?.code ?? 'unknown_error'}`); } console.log(body.data.name, body.request_id); ``` ### Python with `requests` ```python import os import requests api_key = os.environ.get("DAILY_API_KEY") if not api_key: raise RuntimeError("DAILY_API_KEY is required") response = requests.get( "https://api.godaily.co.il/v1/business", headers={"Accept": "application/json", "Authorization": f"Bearer {api_key}"}, timeout=30, ) body = response.json() if not response.ok: request_id = body.get("request_id", "not-returned") code = body.get("error", {}).get("code", "unknown_error") raise RuntimeError(f"Daily API {response.status_code} ({request_id}): {code}") print(body["data"]["name"], body["request_id"]) ``` ## 4. Understand the response ```json { "data": { "id": "0b703598-20d1-4eeb-9012-12db41ac8018", "object": "business", "name": "סטודיו נורת׳סטאר בע״מ", "english_name": "Northstar Studio Ltd.", "business_number": "515990281", "business_type": "company", "email": "finance@northstar.test", "phone": "+972-3-555-0142", "address": { "street": "HaArba’a 28", "city": "Tel Aviv-Yafo", "postal_code": "6473925", "country": "IL" }, "created_at": "2025-02-03T08:30:00.000Z", "updated_at": "2026-07-21T11:45:00.000Z" }, "request_id": "req_docsquickstart01" } ``` Single-resource responses use `data`; list responses use `data` plus `page`. Every JSON response includes `request_id`, and the same identifier is returned in the `X-Request-ID` header when Nginx or the application creates it. ## 5. Rotate or revoke Rotate a key from the same API-key screen. The previous secret remains valid for 24 hours so you can deploy the replacement safely. Revoke a compromised or retired key immediately; revocation has no grace period. --- # Daily Public API Canonical page: https://docs.godaily.co.il/docs/ The Daily Public API provides business-scoped, read-only access to the data already managed in Daily. Use it to synchronize customers and suppliers, read sales and financial documents, retrieve products and inventory, and integrate leads, payments, and tasks with your own server-side systems. ## API at a glance | Property | Value | | --- | --- | | Production base URL | `https://api.godaily.co.il/v1` | | Current version | `v1` | | Authentication | Bearer API key | | Supported methods | `GET` and `HEAD` | | Data scope | The active business bound to the key | | Default / maximum page size | 50 / 100 | | Response format | JSON | Daily exposes no write operations in `v1`. An API key cannot create, edit, or delete business data. ## What you can retrieve - Business identity and contact details - Customers and suppliers - Leads - Products and raw materials - Documents, line items, and short-lived PDF download links - Recorded payments without sensitive payment details - Inventory levels and movements - Tasks and their business relationships ## Five-minute quickstart 1. Open [API keys in the Daily application](https://app.godaily.co.il/api-keys). 2. Create a key with the **פרטי העסק** (`business:read`) permission. 3. Save the one-time key in your server's secret manager or as `DAILY_API_KEY` in a secure local shell. 4. Send `GET https://api.godaily.co.il/v1/business` with `Authorization: Bearer $DAILY_API_KEY`. 5. Record the response's `request_id`; Daily support can use it to trace a request safely. Continue with the [complete getting-started guide](https://docs.godaily.co.il/docs/getting-started). ## Integration boundaries The API is designed for server-to-server integrations. Never ship a Daily API key in a browser bundle, desktop client, or mobile application. The documentation playground is an explicit testing exception: its key exists only in the current page's React memory and requests go directly to Daily. > Daily API keys are secrets. Do not put them in source control, URLs, logs, issue trackers, or chat messages. --- # Pagination Canonical page: https://docs.godaily.co.il/docs/pagination 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 parameter | Behavior | | --- | --- | | `limit` | Integer from 1 to 100; default 50 | | `cursor` | Opaque string, maximum 512 characters | | `page.has_more` | `true` when another page was observed | | `page.next_cursor` | Next 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 ```bash 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 ```ts type Page = { 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 ```python 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. --- # PDF access Canonical page: https://docs.godaily.co.il/docs/pdf-access Documents with `pdf_available: true` can produce a temporary download URL: `GET /documents/{id}/pdf` The operation requires the **מסמכים** (`documents:read`) permission. It returns metadata, not the PDF bytes: ```json { "data": { "id": "813d0b3f-ab6c-43d4-9173-8f224566ba2f", "object": "document_pdf", "url": "https://files.daily.test/documents/invoice-1042.pdf?expires=300", "expires_at": "2026-07-21T12:05:00.000Z", "file_name": "invoice-1042.pdf" }, "request_id": "req_docspdf00001" } ``` The signed URL expires five minutes after issue. Download immediately and never persist, log, analyze, or share it. If it expires, authenticate to Daily again and request a new URL. ## Download safely with TypeScript ```ts import { writeFile } from 'node:fs/promises'; const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); const listResponse = await fetch('https://api.godaily.co.il/v1/documents?limit=100', { headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}` }, }); const list = await listResponse.json(); if (!listResponse.ok) throw new Error(`Daily API ${listResponse.status} (${list.request_id})`); const document = list.data.find((item: { pdf_available: boolean }) => item.pdf_available); if (!document) throw new Error('No document with a PDF is available'); const linkResponse = await fetch(`https://api.godaily.co.il/v1/documents/${encodeURIComponent(document.id)}/pdf`, { headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}` }, }); const link = await linkResponse.json(); if (!linkResponse.ok) throw new Error(`Daily API ${linkResponse.status} (${link.request_id})`); const pdfResponse = await fetch(link.data.url, { redirect: 'error' }); if (!pdfResponse.ok) throw new Error(`PDF download failed with HTTP ${pdfResponse.status}`); const contentType = pdfResponse.headers.get('content-type')?.toLowerCase(); if (contentType !== 'application/pdf') throw new Error(`Unexpected PDF content type: ${contentType ?? 'missing'}`); const bytes = new Uint8Array(await pdfResponse.arrayBuffer()); if (bytes.length < 5 || new TextDecoder('ascii').decode(bytes.slice(0, 5)) !== '%PDF-') { throw new Error('Downloaded content is not a PDF'); } await writeFile(link.data.file_name, bytes, { mode: 0o600 }); ``` ## Download safely with Python ```python import os from pathlib import Path import requests api_key = os.environ.get("DAILY_API_KEY") if not api_key: raise RuntimeError("DAILY_API_KEY is required") headers = {"Accept": "application/json", "Authorization": f"Bearer {api_key}"} documents_response = requests.get( "https://api.godaily.co.il/v1/documents", params={"limit": 100}, headers=headers, timeout=30 ) documents = documents_response.json() if not documents_response.ok: raise RuntimeError(f"Daily API {documents_response.status_code} ({documents.get('request_id')})") document = next((item for item in documents["data"] if item["pdf_available"]), None) if not document: raise RuntimeError("No document with a PDF is available") link_response = requests.get( f"https://api.godaily.co.il/v1/documents/{document['id']}/pdf", headers=headers, timeout=30, ) link = link_response.json() if not link_response.ok: raise RuntimeError(f"Daily API {link_response.status_code} ({link.get('request_id')})") pdf = requests.get(link["data"]["url"], timeout=30, allow_redirects=False) pdf.raise_for_status() if pdf.headers.get("Content-Type", "").split(";", 1)[0].lower() != "application/pdf": raise RuntimeError("Unexpected PDF content type") if not pdf.content.startswith(b"%PDF-"): raise RuntimeError("Downloaded content is not a PDF") target = Path(link["data"]["file_name"]).name Path(target).write_bytes(pdf.content) os.chmod(target, 0o600) ``` Use a fixed download directory, sanitize the returned filename as shown, cap acceptable file size for your system, and scan untrusted files before further processing. --- # Permissions Canonical page: https://docs.godaily.co.il/docs/permissions Select at least one read permission when creating a key. The API checks the required permission after authentication, subscription, and IP restrictions. A missing permission returns `403 insufficient_permission`. | Product label (exact) | Permission | Protected endpoints | Purpose | | --- | --- | --- | --- | | פרטי העסק | `business:read` | `GET /business` | Business identity, contact details, and basic configuration. | | לקוחות | `customers:read` | `GET /customers`, `GET /customers/{id}` | Customer records and their saved contact data. | | ספקים | `suppliers:read` | `GET /suppliers`, `GET /suppliers/{id}` | Supplier records and their saved contact data. | | לידים | `leads:read` | `GET /leads`, `GET /leads/{id}` | Leads, contact data, status, and assigned owner summary. | | מוצרים ושירותים | `products:read` | `GET /products`, `GET /products/{id}` | Products, raw materials, prices, and catalog metadata. | | מסמכים | `documents:read` | `GET /documents`, `GET /documents/{id}`, `GET /documents/{id}/pdf` | Documents, line items, relationships, and available PDFs. | | תשלומים | `payments:read` | `GET /payments`, `GET /payments/{id}` | Recorded payments and document relationships, without sensitive payment details. | | מלאי | `inventory:read` | `GET /inventory`, `GET /inventory/movements` | Inventory levels and inventory movements. | | משימות | `tasks:read` | `GET /tasks`, `GET /tasks/{id}` | Tasks, dates, statuses, and linked business objects. | ## Least privilege Create a separate key per integration and enable only the rows it needs. This limits exposure, makes usage visible by key, and lets you rotate or revoke one integration without interrupting another. Permissions can be edited later in Daily. Removing a permission takes effect on subsequent requests; no new key is required. ## Missing-permission response ```json { "error": { "type": "authorization_error", "code": "insufficient_permission", "message": "This API key cannot access customers." }, "request_id": "req_docspermissions01" } ``` Treat this response as configuration failure. Do not retry it automatically; ask the primary business owner to review the key's permissions. --- # API playground Canonical page: https://docs.godaily.co.il/docs/playground Use the playground for short, controlled validation. Production applications must call Daily from a trusted backend. The playground sends no data through a documentation server or third-party proxy. > Refresh or close the page when finished. The key and response are cleared because they are never persisted. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Rate limits Canonical page: https://docs.godaily.co.il/docs/rate-limits Daily enforces rate limits in Nginx before the application: | Limit | Sustained rate | Burst capacity | Key | | --- | --- | --- | --- | | API key | 5 requests per second | 20 immediate excess requests | Public key identifier | | Client IP | 20 requests per second | 40 immediate excess requests | Source IP | Both limits apply. Requests within the burst are accepted without deliberate delay; once either bucket is exhausted, Nginx returns `429`. ```http HTTP/2 429 Content-Type: application/json Retry-After: 1 X-Request-ID: req_edgeratelimit01 Cache-Control: private, no-store ``` ```json { "error": { "type": "rate_limit_error", "code": "rate_limit_exceeded", "message": "Too many requests." }, "request_id": "req_edgeratelimit01" } ``` The edge response uses `Retry-After: 1`. Temporary upstream failures use `503 service_unavailable` with `Retry-After: 5`; treat them separately. ## Retry strategy Honor `Retry-After`, then use capped exponential backoff with random jitter. Retry `429` and transient `503` responses only. Do not retry authentication, permission, filter, or not-found errors automatically. ```ts const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); async function getWithBackoff(url: string, maxAttempts = 6): Promise { for (let attempt = 0; attempt < maxAttempts; attempt += 1) { const response = await fetch(url, { headers: { Accept: 'application/json', Authorization: `Bearer ${apiKey}` }, }); if (response.status !== 429 && response.status !== 503) return response; if (attempt === maxAttempts - 1) return response; const retryAfter = Number(response.headers.get('retry-after')); const baseMs = Number.isFinite(retryAfter) && retryAfter >= 0 ? retryAfter * 1_000 : Math.min(30_000, 500 * 2 ** attempt); const jitterMs = Math.floor(Math.random() * Math.max(1, baseMs * 0.25)); await new Promise((resolve) => setTimeout(resolve, baseMs + jitterMs)); } throw new Error('Unreachable retry state'); } const response = await getWithBackoff('https://api.godaily.co.il/v1/customers?limit=100'); const body = await response.json(); if (!response.ok) throw new Error(`Daily API ${response.status} (${body.request_id})`); console.log(body.data.length); ``` ## What counts Every request reaching the public `/v1` Nginx location consumes capacity, including each pagination page, browser preflight, and request that later fails authentication, permission, filtering, or lookup. Production integrations should use server-to-server requests and avoid browser preflights. Prefer `limit=100`, keep concurrency below the sustained limits, and coordinate workers sharing a key or NAT address. --- # Integration recipes Canonical page: https://docs.godaily.co.il/docs/recipes ## Synchronize all customers Use `limit=100`, follow `next_cursor` until it is `null`, and upsert by customer ID. The complete cURL, TypeScript, and Python loops in [Pagination](https://docs.godaily.co.il/docs/pagination) operate on `/customers` and check every response. For an initial import, do not set time filters. Save a synchronization start timestamp before page 1, then use it for the next incremental run only after the full traversal succeeds. ## Incrementally retrieve updated data Customers, suppliers, leads, products, documents, payments, inventory levels, and tasks support `updated_after`. They also use a stable `updated_at`/ID cursor order. ```ts type DailyPage = { data: T[]; page: { next_cursor: string | null }; request_id: string }; const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); async function* updatedSince(resource: string, highWaterMark: string): AsyncGenerator { let cursor: string | null = null; do { const url = new URL(`https://api.godaily.co.il/v1/${resource}`); url.searchParams.set('updated_after', highWaterMark); 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 DailyPage & { error?: { code: string } }; if (!response.ok) throw new Error(`Daily API ${response.status} (${body.request_id}): ${body.error?.code}`); yield* body.data; cursor = body.page.next_cursor; } while (cursor); } for await (const customer of updatedSince<{ id: string; updated_at: string }>('customers', '2026-07-01T00:00:00.000Z')) { console.log(customer.id, customer.updated_at); } ``` Use overlap plus idempotent upserts. Inventory movements support `created_after`, not `updated_after`, and are stable by `created_at`/ID. Periodically full-scan if your integration requires assurance beyond creation-only movement retrieval. ## Retrieve suppliers, products, and documents These commands fail on non-2xx responses and print the actual response envelope: ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" for resource in suppliers products documents; do curl --fail-with-body --silent --show-error \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ "https://api.godaily.co.il/v1/${resource}?limit=100" printf '\n' done ``` Each resource needs its own exact permission: **ספקים**, **מוצרים ושירותים**, and **מסמכים**. ## Download a document PDF List documents, select one with `pdf_available: true`, request `GET /documents/{id}/pdf`, and download the signed URL immediately. Validate HTTPS, HTTP status, content type, size, and the `%PDF-` signature. See [PDF access](https://docs.godaily.co.il/docs/pdf-access) for complete TypeScript and Python implementations. ## Handle rate limiting safely When `429` is returned, honor `Retry-After: 1`; for edge `503`, honor `Retry-After: 5`. Add exponential backoff and random jitter, cap retries, and avoid retrying permanent 4xx responses. See the tested client pattern in [Rate limits](https://docs.godaily.co.il/docs/rate-limits). ## Rotate a key without downtime 1. Rotate the existing key in [Daily → API keys](https://app.godaily.co.il/api-keys). 2. Save the new one-time secret in your secret manager. 3. Deploy it to every caller and make a health request. 4. Confirm successful request IDs and key last-use behavior. 5. Remove the old secret before its 24-hour grace period expires. No public API operation rotates keys. Do not automate rotation by calling private application endpoints. ## Troubleshoot permission failures For `403 insufficient_permission`: 1. Record `request_id` and the requested path, never the Authorization header. 2. Map the path to the [permission table](https://docs.godaily.co.il/docs/permissions). 3. Ask the primary business owner to edit that key in Daily. 4. Retry once after the permission change. Distinguish permission failures from `api_access_inactive` and `ip_not_allowed`; each requires a different configuration change. --- # OpenAPI reference Canonical page: https://docs.godaily.co.il/docs/reference This reference is generated from the committed OpenAPI 3.1 contract. Use the [secure playground](https://docs.godaily.co.il/docs/playground) for direct test requests; the generated renderer's built-in credential storage is intentionally disabled. [View the complete OpenAPI contract as JSON](https://docs.godaily.co.il/openapi.json) or [YAML](https://docs.godaily.co.il/openapi.yaml). --- # Requests and responses Canonical page: https://docs.godaily.co.il/docs/requests-responses ## Request conventions - Base URL: `https://api.godaily.co.il/v1` - Methods: `GET` and `HEAD` only. Other methods return `405 method_not_allowed` with `Allow: GET, HEAD`. - Accept: use `Accept: application/json`. - Authentication: send `Authorization: Bearer $DAILY_API_KEY`. - Query strings longer than 2,048 characters return `400 invalid_filter`. - Unknown query parameters are rejected; they are not silently ignored. There are no request bodies in `v1`. ## IDs Resource IDs are UUID strings. Use them exactly as returned. Invalid or path-like IDs return `400 invalid_filter`; an absent or out-of-scope ID returns `404 resource_not_found`. ## Dates, times, and timezones Timestamp fields such as `created_at`, `updated_at`, and `due_at` use ISO 8601 in UTC, for example `2026-07-21T11:45:00.000Z`. Date-only fields such as `issue_date`, `payment_date`, and `due_date` use `YYYY-MM-DD` and do not carry a timezone. Filtering timestamps must be strict ISO 8601 values. `created_after` and `updated_after` are exclusive (`>`), not inclusive. ## Currency and monetary values Currency codes are three-letter strings such as `ILS`. Monetary fields ending in `_minor` are integers in the currency's minor unit. For ILS, `218300` means ₪2,183.00. Do not parse these values as floating-point major units. Inventory quantities and document line quantities are fixed three-decimal strings, such as `"42.000"`, to preserve decimal precision. ## Nullability and collections Nullable fields are present with `null` when no value is available. Arrays are present as empty arrays when no values exist. Do not assume an email, phone, owner, due date, product relationship, or PDF is always present. ## Response envelopes Single resources: ```json { "data": { "id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "object": "product" }, "request_id": "req_docsresponse01" } ``` Collections: ```json { "data": [], "page": { "has_more": false, "next_cursor": null }, "request_id": "req_docsresponse02" } ``` Errors: ```json { "error": { "type": "invalid_request_error", "code": "invalid_filter", "message": "One or more request parameters are invalid." }, "request_id": "req_docsresponse03" } ``` ## Request IDs Daily returns `request_id` in JSON and `X-Request-ID` at the HTTP edge. You may supply `X-Request-ID` using 8–100 ASCII letters, numbers, underscores, or hyphens. Invalid values and values resembling a Daily key are replaced. Record the ID beside your own trace ID, but never attach the Authorization header when contacting support. ## Caching and compatibility Authenticated responses use private no-store/no-cache headers. Do not put them in shared caches. Clients should ignore new object fields to remain forward-compatible; existing documented fields will not be repurposed within `v1` without a breaking-version decision. --- # Business Canonical page: https://docs.godaily.co.il/docs/resources/business **Permission:** פרטי העסק (`business:read`) ## Retrieve the business `GET /business` This endpoint accepts no query parameters. It resolves business scope from the authenticated key and returns the active business only. ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" curl --fail-with-body --silent --show-error \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ 'https://api.godaily.co.il/v1/business' ``` ```json { "data": { "id": "0b703598-20d1-4eeb-9012-12db41ac8018", "object": "business", "name": "סטודיו נורת׳סטאר בע״מ", "english_name": "Northstar Studio Ltd.", "business_number": "515990281", "business_type": "company", "email": "finance@northstar.test", "phone": "+972-3-555-0142", "address": { "street": "HaArba’a 28", "city": "Tel Aviv-Yafo", "postal_code": "6473925", "country": "IL" }, "created_at": "2025-02-03T08:30:00.000Z", "updated_at": "2026-07-21T11:45:00.000Z" }, "request_id": "req_docsbusiness001" } ``` `english_name`, `business_number`, `email`, `phone`, and address fields can be `null`. `country` is currently `IL`. Verified errors include authentication and subscription failures, IP or permission denial, invalid query parameters, rate limiting, not found, and internal or upstream failure. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Customers and suppliers Canonical page: https://docs.godaily.co.il/docs/resources/customers-suppliers Customers and suppliers share a response shape but use distinct permissions and routes. | Resource | List | Retrieve | Permission | | --- | --- | --- | --- | | Customers | `GET /customers` | `GET /customers/{id}` | לקוחות (`customers:read`) | | Suppliers | `GET /suppliers` | `GET /suppliers/{id}` | ספקים (`suppliers:read`) | ## List parameters Both lists support `limit`, `cursor`, `created_after`, `updated_after`, `status=active|inactive`, and `search`. Search covers name, business number, email, and contact person. Results sort by `updated_at` descending and then ID descending. ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" curl --fail-with-body --silent --show-error --get \ 'https://api.godaily.co.il/v1/customers' \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ --data-urlencode 'status=active' \ --data-urlencode 'search=Orion' \ --data-urlencode 'limit=50' ``` ## Customer response ```json { "data": [{ "id": "44f34dad-a427-4c65-ae26-b0a43f8f65f7", "object": "customer", "type": "customer", "name": "Orion Retail", "business_number": "515880391", "contact_person": "Noa Levi", "email": "billing@orion-retail.test", "additional_emails": ["ops@orion-retail.test"], "phone": "+972-52-555-0128", "phones": [{ "value": "+972-52-555-0128", "primary": true }], "address": { "street": "HaArba’a", "street_number": "28", "city": "Tel Aviv-Yafo", "postal_code": "6473925", "country_code": "IL" }, "status": "active", "currency": "ILS", "tags": ["retail", "priority"], "created_at": "2025-06-17T09:20:00.000Z", "updated_at": "2026-07-19T14:12:00.000Z" }], "page": { "has_more": false, "next_cursor": null }, "request_id": "req_docscustomer01" } ``` The first ordered phone is also exposed as `phone`. `additional_emails` excludes the primary email. Address and contact fields may be `null`; arrays remain present. Detail operations accept only a UUID path parameter. Missing and out-of-scope IDs return `404 resource_not_found`; invalid UUIDs return `400 invalid_filter`. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Documents Canonical page: https://docs.godaily.co.il/docs/resources/documents **Permission:** מסמכים (`documents:read`) | Operation | Path | | --- | --- | | List | `GET /documents` | | Retrieve | `GET /documents/{id}` | | Get temporary PDF URL | `GET /documents/{id}/pdf` | The list supports common cursor and time filters, search over title and customer-name snapshot, and these statuses: `open`, `converted`, `pending_payment`, `closed`, `credited`, `returned`, `partially_paid`, `partially_credited`, `partially_returned`. It sorts by `updated_at` descending, then ID descending. ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" curl --fail-with-body --silent --show-error --get \ 'https://api.godaily.co.il/v1/documents' \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ --data-urlencode 'updated_after=2026-07-01T00:00:00.000Z' \ --data-urlencode 'limit=100' ``` ```json { "id": "813d0b3f-ab6c-43d4-9173-8f224566ba2f", "object": "document", "document_type": "invoice", "document_number": 1042, "title": "Invoice 1042", "status": "pending_payment", "language": "en", "customer": { "id": "44f34dad-a427-4c65-ae26-b0a43f8f65f7", "name": "Orion Retail" }, "issue_date": "2026-07-15", "due_date": "2026-08-14", "currency": "ILS", "subtotal_minor": 185000, "discount_minor": null, "vat_minor": 33300, "total_minor": 218300, "payment_status": "unpaid", "pdf_available": true, "line_items": [{ "id": "ccf43b06-f708-41b7-8408-a96f31b637f2", "line_number": 1, "product_id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "name": "Brand workshop", "sku": "WORKSHOP-01", "quantity": "1.000", "unit_price_minor": 185000, "total_minor": 185000, "currency": "ILS", "vat_included": false }], "related_document_ids": [], "created_at": "2026-07-15T08:05:00.000Z", "updated_at": "2026-07-15T08:06:00.000Z" } ``` `due_date` is the issue date for cash terms, issue date plus configured net days for net terms, and otherwise `null`. `vat_minor` is `total_minor - subtotal_minor`. `payment_status` is derived from document status. Use `pdf_available` before requesting the PDF URL. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Resource reference Canonical page: https://docs.godaily.co.il/docs/resources/index The public API currently implements 18 read operations across nine resource groups. There are no write operations, webhooks, or OAuth flows in `v1`. | Resource | Operations | Required permission | | --- | --- | --- | | Business | `GET /business` | פרטי העסק | | Customers | `GET /customers`, `GET /customers/{id}` | לקוחות | | Suppliers | `GET /suppliers`, `GET /suppliers/{id}` | ספקים | | Leads | `GET /leads`, `GET /leads/{id}` | לידים | | Products | `GET /products`, `GET /products/{id}` | מוצרים ושירותים | | Documents | `GET /documents`, `GET /documents/{id}`, `GET /documents/{id}/pdf` | מסמכים | | Payments | `GET /payments`, `GET /payments/{id}` | תשלומים | | Inventory | `GET /inventory`, `GET /inventory/movements` | מלאי | | Tasks | `GET /tasks`, `GET /tasks/{id}` | משימות | Collection operations return cursor-paginated envelopes. Detail operations return one object and reject query parameters. All operations require a bearer key and an eligible subscription. Use the resource pages for field semantics and workflows, or open the [generated OpenAPI reference](https://docs.godaily.co.il/docs/reference) for every parameter, schema, sample, and error response. --- # Inventory Canonical page: https://docs.godaily.co.il/docs/resources/inventory **Permission:** מלאי (`inventory:read`) ## Inventory levels `GET /inventory` returns only inventory-tracked products. It supports common cursor and time filters, `status=active|inactive`, and search over product name. Sort order is `updated_at` descending and then ID descending. ```json { "id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "object": "inventory_level", "product_id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "product_name": "Workshop workbook", "sku": "BOOK-01", "quantity": "42.000", "low_stock_threshold": "10.000", "status": "active", "created_at": "2025-12-01T09:00:00.000Z", "updated_at": "2026-07-20T09:16:00.000Z" } ``` ## Inventory movements `GET /inventory/movements` supports `limit`, `cursor`, `created_after`, and direction through `status=increase|decrease`. It rejects `updated_after` and `search`. Results sort by `created_at` descending and ID descending. ```python import os import requests api_key = os.environ.get("DAILY_API_KEY") if not api_key: raise RuntimeError("DAILY_API_KEY is required") response = requests.get( "https://api.godaily.co.il/v1/inventory/movements", params={"status": "decrease", "created_after": "2026-07-01T00:00:00.000Z", "limit": 100}, headers={"Authorization": f"Bearer {api_key}", "Accept": "application/json"}, timeout=30, ) body = response.json() if not response.ok: raise RuntimeError(f"Daily API {response.status_code} ({body.get('request_id')})") print(body["data"]) ``` ```json { "id": "2d545552-8dfa-4f5c-86d7-293390f6ec3e", "object": "inventory_movement", "product_id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "product_name": "Workshop workbook", "sku": "BOOK-01", "document_id": "813d0b3f-ab6c-43d4-9173-8f224566ba2f", "direction": "decrease", "quantity": "2.000", "created_at": "2026-07-20T09:16:00.000Z" } ``` Quantities are fixed three-decimal strings. Movement pages do not include `updated_at`. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Leads Canonical page: https://docs.godaily.co.il/docs/resources/leads **Permission:** לידים (`leads:read`) | Operation | Path | | --- | --- | | List | `GET /leads` | | Retrieve | `GET /leads/{id}` | The list supports common cursor and time filters, `search` over name, contact name, email, and phone, and these statuses: `new`, `contacted`, `in_progress`, `proposal`, `negotiation`, `won`, `lost`. Sort order is `updated_at` descending, then ID descending. ```ts const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); const url = new URL('https://api.godaily.co.il/v1/leads'); url.searchParams.set('status', 'proposal'); url.searchParams.set('updated_after', '2026-07-01T00:00:00.000Z'); const response = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/json' } }); const body = await response.json(); if (!response.ok) throw new Error(`Daily API ${response.status} (${body.request_id})`); console.log(body.data); ``` ```json { "id": "20c85f5f-d823-411f-bbf7-f5b76ea77235", "object": "lead", "name": "Nova Hospitality", "contact_name": "Eitan Bar", "email": "eitan@nova-hospitality.test", "phone": "+972-54-555-0174", "address": "Herzliya", "source": "website", "status": "proposal", "owner": { "id": "913f5ab6-9525-483c-9aa1-73d561b8bfa8", "display_name": "Maya Cohen" }, "converted_customer_id": null, "created_at": "2026-07-08T07:45:00.000Z", "updated_at": "2026-07-20T10:05:00.000Z" } ``` Contact fields, source, owner, and converted customer can be `null`. The owner is returned only when the assigned sales agent belongs to the authenticated business. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Payments Canonical page: https://docs.godaily.co.il/docs/resources/payments **Permission:** תשלומים (`payments:read`) | Operation | Path | | --- | --- | | List | `GET /payments` | | Retrieve | `GET /payments/{id}` | The list supports `limit`, `cursor`, `created_after`, `updated_after`, and only `status=recorded`. Search is not supported. Results sort by `updated_at` descending and then ID descending. ```bash set -euo pipefail : "${DAILY_API_KEY:?DAILY_API_KEY is required}" curl --fail-with-body --silent --show-error \ --header "Authorization: Bearer ${DAILY_API_KEY}" \ --header 'Accept: application/json' \ 'https://api.godaily.co.il/v1/payments?status=recorded&limit=100' ``` ```json { "id": "9eaf89fa-dc55-4130-ac85-598f8a5430c5", "object": "payment", "document_id": "813d0b3f-ab6c-43d4-9173-8f224566ba2f", "customer_id": "44f34dad-a427-4c65-ae26-b0a43f8f65f7", "amount_minor": 218300, "currency": "ILS", "payment_method": "bank_transfer", "payment_date": "2026-07-20", "status": "recorded", "created_at": "2026-07-20T09:15:00.000Z", "updated_at": "2026-07-20T09:15:00.000Z" } ``` Payment methods normalize to `card`, `cash`, `bank_transfer`, `check`, `paypal`, or `other`. The API deliberately omits provider transaction IDs, card digits or tokens, CVV, and bank account details. `customer_id` can be `null` if the safe business relationship cannot be established. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Products Canonical page: https://docs.godaily.co.il/docs/resources/products **Permission:** מוצרים ושירותים (`products:read`) | Operation | Path | | --- | --- | | List | `GET /products` | | Retrieve | `GET /products/{id}` | The list supports common cursor and time filters, `status=active|inactive`, and search over product name, SKU, and barcode. Results sort by `updated_at` descending and then ID descending. ```python import os import requests api_key = os.environ.get("DAILY_API_KEY") if not api_key: raise RuntimeError("DAILY_API_KEY is required") response = requests.get( "https://api.godaily.co.il/v1/products", params={"status": "active", "limit": 100}, headers={"Authorization": f"Bearer {api_key}", "Accept": "application/json"}, timeout=30, ) body = response.json() if not response.ok: raise RuntimeError(f"Daily API {response.status_code} ({body.get('request_id')})") print([(item["sku"], item["price_minor"]) for item in body["data"]]) ``` ```json { "id": "44cfbbd5-185d-4c9d-8597-588c25e574e8", "object": "product", "type": "product", "name": "Brand workshop", "description": null, "sku": "WORKSHOP-01", "barcode": "7290012345678", "price_minor": 185000, "currency": "ILS", "vat_behavior": "excluding_vat", "unit": null, "status": "active", "inventory_tracked": false, "created_at": "2025-11-02T12:00:00.000Z", "updated_at": "2026-07-18T08:15:00.000Z" } ``` `type` is `product` or `raw_material`. `price_minor` is an integer minor-unit amount. `description` and `unit` are currently always `null`; clients should still follow the published schema. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Tasks Canonical page: https://docs.godaily.co.il/docs/resources/tasks **Permission:** משימות (`tasks:read`) | Operation | Path | | --- | --- | | List | `GET /tasks` | | Retrieve | `GET /tasks/{id}` | The list supports common cursor and time filters, search over task title, and `status=open|completed|canceled`. Results sort by `updated_at` descending and then ID descending. ```ts const apiKey = process.env.DAILY_API_KEY; if (!apiKey) throw new Error('DAILY_API_KEY is required'); const response = await fetch('https://api.godaily.co.il/v1/tasks?status=open&limit=100', { headers: { Authorization: `Bearer ${apiKey}`, Accept: 'application/json' }, }); const body = await response.json(); if (!response.ok) throw new Error(`Daily API ${response.status} (${body.request_id})`); console.log(body.data); ``` ```json { "id": "9139e779-dd20-4418-b67a-20975607ce40", "object": "task", "title": "Confirm workshop schedule", "description": null, "status": "open", "priority": "high", "due_date": "2026-07-25", "due_at": "2026-07-25T07:00:00.000Z", "customer_id": "44f34dad-a427-4c65-ae26-b0a43f8f65f7", "document_id": "813d0b3f-ab6c-43d4-9173-8f224566ba2f", "lead_id": "20c85f5f-d823-411f-bbf7-f5b76ea77235", "assigned_user": { "id": "913f5ab6-9525-483c-9aa1-73d561b8bfa8", "display_name": "Maya Cohen" }, "created_at": "2026-07-20T10:10:00.000Z", "updated_at": "2026-07-21T08:30:00.000Z" } ``` Priority derives from the task's starred state. Relationship IDs, due values, and assigned user can be `null`. `status=unknown` may appear in a response when legacy stored text does not map to one of the three filterable statuses; it is not accepted as a filter. [Open the secure API playground](https://docs.godaily.co.il/docs/playground). --- # Security best practices Canonical page: https://docs.godaily.co.il/docs/security ## Production checklist - Call Daily from trusted server-side workloads only. - Store keys in a managed secret store or encrypted environment injection. - Create a separate key for each integration and environment. - Grant only the permissions the integration uses. - Restrict stable workloads with IPv4, IPv6, or CIDR allowlists. - Choose an expiration appropriate to your rotation process. - Rotate before expiration and verify the replacement during the 24-hour grace window. - Revoke keys immediately when no longer needed. - Never put keys in URLs, frontend bundles, mobile apps, source control, build artifacts, tickets, or chat. - Redact `Authorization`, API-key patterns, signed PDF URLs, and sensitive response fields from logs and error reporting. - Store only required response data and apply your own access and retention controls. ## Logging Useful request telemetry includes HTTP method, normalized public route, status, duration, your internal trace ID, and Daily `request_id`. It must not include the raw query if search values are sensitive, the Authorization header, a complete resource response, or signed download URLs. Daily accepts a safe `X-Request-ID` and returns it for correlation. Generate an opaque identifier; never reuse a customer email, business number, or API key as a request ID. ## Exposure response If a key may have leaked: 1. Revoke it immediately in [Daily → API keys](https://app.godaily.co.il/api-keys). Do not rotate and leave the exposed key valid during grace. 2. Create a replacement with minimum permissions and, where practical, an IP allowlist. 3. Update the secret store and redeploy affected workloads. 4. Search logs, repositories, CI output, support systems, and artifacts for the exposed value; remove it under your incident procedures. 5. Review key last-use information and integration logs for unexpected routes, times, or source networks. 6. Record relevant Daily request IDs and contact [Daily support](https://wa.me/972523914844) without sending a key. ## Browser playground The portal has no analytics or third-party scripts. Its playground keeps the key only in component state, uses direct CORS requests with `credentials: omit`, never constructs a URL containing the key, and clears state on refresh. This does not make browser-embedded keys safe for your own application. --- # API versioning Canonical page: https://docs.godaily.co.il/docs/versioning The API version is part of every public path: ```text https://api.godaily.co.il/v1 ``` Only `v1` exists. The documentation therefore shows a version indicator, not a selector. ## Compatibility within v1 Integrations should tolerate additive changes such as new nullable response fields, new enum values where the schema permits them, and new endpoints. Ignore unknown object properties and avoid exhaustive parsing that crashes on a value it does not recognize. A change that removes or repurposes a documented field, changes its fundamental type, changes an existing route's meaning, or requires incompatible client behavior would require an explicit versioning and communication decision. This documentation does not promise a deprecation timeline that Daily has not established. Monitor the [changelog](https://docs.godaily.co.il/docs/changelog) and the committed OpenAPI version in your integration review process. Pin generated clients to a reviewed OpenAPI artifact and update deliberately. ---