{
  "openapi": "3.1.0",
  "info": {
    "title": "Basketly API",
    "version": "1.3.0",
    "description": "REST API of Basketly (app.basketly.io): shop orders and buyers, products and their diagnosis, product feeds and feed flows, image templates, server-to-server conversions, people and tasks, campaign and creative reports, self-check, background jobs and webhooks. Authenticate with an organisation API key: `Authorization: Bearer bsk_live_…`.",
    "x-pl-description": "REST API Basketly (app.basketly.io): zamówienia ze sklepu i kupujący, produkty i ich diagnoza, feedy produktowe i przepływy feedów, szablony grafik, konwersje serwer–serwer, osoby i zadania, raporty kampanii i kreacji, autodiagnostyka, zadania w tle oraz webhooki. Uwierzytelnianie kluczem API organizacji: `Authorization: Bearer bsk_live_…`.",
    "contact": {
      "name": "Basketly",
      "url": "https://basketly.io"
    },
    "x-generated-by": "scripts/gen-openapi.py"
  },
  "servers": [
    {
      "url": "https://app.basketly.io/api/v1"
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "tags": [
    {
      "name": "Keys",
      "description": "The calling key.",
      "x-pl-description": "Używany klucz."
    },
    {
      "name": "Contacts",
      "description": "People of the Klienci page.",
      "x-pl-description": "Osoby ze strony Klienci."
    },
    {
      "name": "Events",
      "description": "Conversions sent to Meta and their deliveries.",
      "x-pl-description": "Konwersje wysyłane do Meta i ich wysyłki."
    },
    {
      "name": "Work",
      "description": "Tasks.",
      "x-pl-description": "Zadania."
    },
    {
      "name": "Integrations",
      "description": "Where the shop sells, advertises and sends its catalogue.",
      "x-pl-description": "Gdzie sklep sprzedaje, reklamuje się i wysyła katalog."
    },
    {
      "name": "Orders",
      "description": "Shop orders with their lines and buyers.",
      "x-pl-description": "Zamówienia ze sklepu z pozycjami i kupującymi."
    },
    {
      "name": "Products",
      "description": "Products with their diagnosis and manual fixes.",
      "x-pl-description": "Produkty z diagnozą i ręcznymi poprawkami."
    },
    {
      "name": "Feeds",
      "description": "Product feeds, their rules, flows and Google categories.",
      "x-pl-description": "Feedy produktowe, ich reguły, przepływy i kategorie Google."
    },
    {
      "name": "Templates",
      "description": "Image templates for catalogue ads.",
      "x-pl-description": "Szablony grafik do reklam katalogowych."
    },
    {
      "name": "Reports",
      "description": "Campaign and creative numbers.",
      "x-pl-description": "Liczby kampanii i kreacji."
    },
    {
      "name": "Automations",
      "description": "The organisation's automations and their state.",
      "x-pl-description": "Automatyzacje organizacji i ich stan."
    },
    {
      "name": "Diagnostics",
      "description": "The organisation's self-check.",
      "x-pl-description": "Autodiagnostyka organizacji."
    },
    {
      "name": "Jobs",
      "description": "Background work.",
      "x-pl-description": "Prace w tle."
    },
    {
      "name": "Webhooks",
      "description": "Events pushed to your server.",
      "x-pl-description": "Zdarzenia wysyłane na Twój serwer."
    }
  ],
  "paths": {
    "/me": {
      "get": {
        "tags": [
          "Keys"
        ],
        "operationId": "getMe",
        "summary": "Describe the calling key",
        "description": "Organisation, key name, scopes and expiry. A safe first call to check a new key; needs no scope.",
        "x-pl": {
          "summary": "Opis używanego klucza",
          "description": "Organizacja, nazwa klucza, uprawnienia i termin ważności. Bezpieczne pierwsze wywołanie do sprawdzenia nowego klucza; nie wymaga uprawnień."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Me"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/contacts": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "listContacts",
        "summary": "List contacts",
        "description": "People of the Klienci page (merged cards are left out). Filter by tag or exact e-mail or phone.",
        "x-pl": {
          "summary": "Lista osób",
          "description": "Osoby ze strony Klienci (scalone karty są pominięte). Filtruj po tagu albo dokładnym e-mailu lub telefonie."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/order"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "Tag.",
            "x-pl-description": "Tag.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "Exact e-mail (matched by hash).",
            "x-pl-description": "Dokładny e-mail (dopasowanie po skrócie).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "required": false,
            "description": "Exact phone (matched by hash).",
            "x-pl-description": "Dokładny telefon (dopasowanie po skrócie).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "createContact",
        "summary": "Create a contact",
        "description": "Adds a person like „Dodaj osobę” in the panel.",
        "x-pl": {
          "summary": "Dodaj osobę",
          "description": "Dodaje osobę jak „Dodaj osobę” w panelu."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "x-pl-description": "Utworzono",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactCreate"
              }
            }
          }
        }
      }
    },
    "/contacts/{id}": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "getContact",
        "summary": "Get a contact",
        "description": "A merged card answers 409 `contact_merged` with `details.merged_into`.",
        "x-pl": {
          "summary": "Pobierz osobę",
          "description": "Scalona karta zwraca 409 `contact_merged` z `details.merged_into`."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Contacts"
        ],
        "operationId": "updateContact",
        "summary": "Update a contact",
        "description": "Changes name, phone, e-mail or tags; every change is a history line.",
        "x-pl": {
          "summary": "Zmień dane osoby",
          "description": "Zmienia imię, telefon, e-mail lub tagi; każda zmiana to wpis w historii."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ContactUpdate"
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/notes": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "addContactNote",
        "summary": "Add a note",
        "description": "Adds a note, call or meeting to the person's history.",
        "x-pl": {
          "summary": "Dodaj notatkę",
          "description": "Dodaje notatkę, telefon lub spotkanie do historii osoby."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "x-pl-description": "Utworzono",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Note"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NoteCreate"
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/tags": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "changeContactTags",
        "summary": "Add or remove tags",
        "description": "Adds and removes tags without sending the whole list.",
        "x-pl": {
          "summary": "Dodaj lub usuń tagi",
          "description": "Dodaje i usuwa tagi bez wysyłania całej listy."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TagsChange"
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/sms-optout": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "setContactOptout",
        "summary": "Block or allow SMS",
        "description": "Keeps the „nie wysyłaj” list and every person with the same phone in step.",
        "x-pl": {
          "summary": "Zablokuj lub dopuść SMS-y",
          "description": "Utrzymuje listę „nie wysyłaj” i wszystkie osoby z tym samym telefonem w zgodzie."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Contact"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OptoutChange"
              }
            }
          }
        }
      }
    },
    "/events": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "createEvent",
        "summary": "Send a conversion",
        "description": "Server-to-server conversion ingest. The source's active flows map `status` to Meta events and queue one delivery per dataset; dedupe rules are unchanged. Answers 202: queued, not yet sent.",
        "x-pl": {
          "summary": "Wyślij konwersję",
          "description": "Przyjmowanie konwersji serwer–serwer. Aktywne przepływy źródła mapują `status` na zdarzenia Meta i dodają jedną wysyłkę na dataset; zasady deduplikacji bez zmian. Odpowiedź 202: w kolejce, jeszcze nie wysłane."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Accepted into the queue",
            "x-pl-description": "Przyjęto do kolejki",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventAccepted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "events:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventCreate"
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "listEvents",
        "summary": "List events",
        "description": "Conversions with their deliveries; payloads are never returned.",
        "x-pl": {
          "summary": "Lista zdarzeń",
          "description": "Konwersje z wysyłkami; treść zdarzeń nigdy nie jest zwracana."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/order"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Source id.",
            "x-pl-description": "Identyfikator źródła.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Your status.",
            "x-pl-description": "Twój status.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "external_id",
            "in": "query",
            "required": false,
            "description": "Your record id.",
            "x-pl-description": "Twój identyfikator rekordu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/EventList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "events:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/events/{id}": {
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "getEvent",
        "summary": "Get an event",
        "description": "One conversion with the status of each delivery.",
        "x-pl": {
          "summary": "Pobierz zdarzenie",
          "description": "Jedna konwersja ze statusem każdej wysyłki."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Event"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "events:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/deliveries": {
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "listDeliveries",
        "summary": "List deliveries",
        "description": "Delivery status to Meta, e.g. `status=failed&updated_since=…` to follow failures.",
        "x-pl": {
          "summary": "Lista wysyłek",
          "description": "Status wysyłek do Meta, np. `status=failed&updated_since=…`, by śledzić błędy."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/order"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Delivery status.",
            "x-pl-description": "Status wysyłki.",
            "schema": {
              "type": "string",
              "enum": [
                "pending",
                "sending",
                "retry",
                "accepted",
                "failed",
                "cancelled"
              ]
            }
          },
          {
            "name": "event",
            "in": "query",
            "required": false,
            "description": "Event id.",
            "x-pl-description": "Identyfikator zdarzenia.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "target",
            "in": "query",
            "required": false,
            "description": "Receiver id.",
            "x-pl-description": "Identyfikator odbiorcy.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "events:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/campaigns/report": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "campaignReport",
        "summary": "Campaign report",
        "description": "Spend, purchases, purchase value, cost per purchase and ROAS per campaign, ad set or ad — the numbers of the Kampanie page.",
        "x-pl": {
          "summary": "Raport kampanii",
          "description": "Wydatki, zakupy, wartość zakupów, koszt zakupu i ROAS na kampanię, zestaw lub reklamę — liczby ze strony Kampanie."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (range up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (zakres do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "description": "Row level.",
            "x-pl-description": "Poziom wierszy.",
            "schema": {
              "type": "string",
              "enum": [
                "campaign",
                "adset",
                "ad"
              ],
              "default": "campaign"
            }
          },
          {
            "name": "campaign",
            "in": "query",
            "required": false,
            "description": "Only this campaign (for adset/ad level).",
            "x-pl-description": "Tylko ta kampania (dla poziomu adset/ad).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "adset",
            "in": "query",
            "required": false,
            "description": "Only this ad set (ad level).",
            "x-pl-description": "Tylko ten zestaw (poziom ad).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ad_account",
            "in": "query",
            "required": false,
            "description": "Only this Meta ad account (act_… or the bare number); the shop's totals then come only when it is the organisation's only account.",
            "x-pl-description": "Tylko to konto reklamowe Mety (act_… albo sam numer); sumy sklepu pojawiają się wtedy tylko, gdy to jedyne konto organizacji.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/creatives/report": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "creativeReport",
        "summary": "Creative report",
        "description": "Metrics per creative group with weekly momentum and the fatigue rule — the numbers of the Kreacje page.",
        "x-pl": {
          "summary": "Raport kreacji",
          "description": "Metryki na grupę kreacji z trendem tygodniowym i regułą zmęczenia — liczby ze strony Kreacje."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD.",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD.",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "format",
            "in": "query",
            "required": false,
            "description": "Creative format.",
            "x-pl-description": "Format kreacji.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign",
            "in": "query",
            "required": false,
            "description": "Meta campaign id.",
            "x-pl-description": "Identyfikator kampanii Meta.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ad_account",
            "in": "query",
            "required": false,
            "description": "Ad account id.",
            "x-pl-description": "Identyfikator konta reklamowego.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "Tag filter `dimension:value` (hook, creator, offer).",
            "x-pl-description": "Filtr tagu `wymiar:wartość` (hook, creator, offer).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "weeks",
            "in": "query",
            "required": false,
            "description": "Weeks of momentum, 4–8.",
            "x-pl-description": "Liczba tygodni trendu, 4–8.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "meta (default) = Meta's creative groups; google_ads, microsoft_ads, tiktok, pinterest or openai_ads = that platform's ads (and Google's assets) with the platform's figures — the answer is then a ChannelCreatives object.",
            "x-pl-description": "meta (domyślnie) = grupy kreacji Mety; google_ads, microsoft_ads, tiktok, pinterest albo openai_ads = reklamy tej platformy (i zasoby Google) z liczbami platformy — odpowiedź to wtedy obiekt ChannelCreatives.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "google_ads",
                "microsoft_ads",
                "tiktok",
                "pinterest",
                "openai_ads"
              ]
            }
          },
          {
            "name": "active",
            "in": "query",
            "required": false,
            "description": "1 = only active ads.",
            "x-pl-description": "1 = tylko aktywne reklamy.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CreativeReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "creatives:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/jobs": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "listJobs",
        "summary": "List background jobs",
        "description": "Order reads, spend syncs, sheet syncs and other background work of the organisation.",
        "x-pl": {
          "summary": "Lista zadań w tle",
          "description": "Odczyty zamówień, synchronizacje wydatków, arkuszy i inne prace w tle organizacji."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/order"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Job status.",
            "x-pl-description": "Status zadania.",
            "schema": {
              "type": "string",
              "enum": [
                "queued",
                "running",
                "done",
                "failed",
                "cancelled"
              ]
            }
          },
          {
            "name": "kind",
            "in": "query",
            "required": false,
            "description": "Job kinds, comma-separated (the `kind` field, e.g. `shoper_orders,feed_fetch`).",
            "x-pl-description": "Rodzaje zadań po przecinku (pole `kind`, np. `shoper_orders,feed_fetch`).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JobList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "jobs:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/jobs/{number}": {
      "get": {
        "tags": [
          "Jobs"
        ],
        "operationId": "getJob",
        "summary": "Get a job",
        "description": "One job by its number.",
        "x-pl": {
          "summary": "Pobierz zadanie",
          "description": "Jedno zadanie po numerze."
        },
        "parameters": [
          {
            "name": "number",
            "in": "path",
            "required": true,
            "description": "Job number.",
            "x-pl-description": "Numer zadania.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Job"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "jobs:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/webhooks": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhooks",
        "summary": "List webhooks",
        "description": "Webhook subscriptions of the organisation (up to 10).",
        "x-pl": {
          "summary": "Lista webhooków",
          "description": "Subskrypcje webhooków organizacji (do 10)."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "createWebhook",
        "summary": "Create a webhook",
        "description": "Subscribes an HTTPS URL to events. The signing `secret` is returned only here.",
        "x-pl": {
          "summary": "Dodaj webhook",
          "description": "Subskrybuje adres HTTPS na zdarzenia. Sekret podpisu `secret` jest zwracany tylko tutaj."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "x-pl-description": "Utworzono",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookCreate"
              }
            }
          }
        }
      }
    },
    "/webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "getWebhook",
        "summary": "Get a webhook",
        "description": "One subscription with its last result.",
        "x-pl": {
          "summary": "Pobierz webhook",
          "description": "Jedna subskrypcja z ostatnim wynikiem."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "updateWebhook",
        "summary": "Update a webhook",
        "description": "Changes URL, events, description or pauses it; resuming resets the failure count.",
        "x-pl": {
          "summary": "Zmień webhook",
          "description": "Zmienia adres, zdarzenia, opis lub wstrzymuje; wznowienie zeruje licznik błędów."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Webhook"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookUpdate"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "deleteWebhook",
        "summary": "Delete a webhook",
        "description": "Removes the subscription and its queued deliveries.",
        "x-pl": {
          "summary": "Usuń webhook",
          "description": "Usuwa subskrypcję i jej wysyłki w kolejce."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "204": {
            "description": "Deleted",
            "x-pl-description": "Usunięto"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/webhooks/{id}/test": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "testWebhook",
        "summary": "Send a test ping",
        "description": "Queues a signed `ping` event to check your endpoint and signature verification.",
        "x-pl": {
          "summary": "Wyślij próbny ping",
          "description": "Dodaje do kolejki podpisane zdarzenie `ping`, by sprawdzić odbiornik i weryfikację podpisu."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Queued",
            "x-pl-description": "W kolejce",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookTest"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/webhooks/{id}/rotate-secret": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "rotateWebhookSecret",
        "summary": "Rotate the signing secret",
        "description": "Replaces the signing secret at once; the new `secret` is returned only here. Deliveries still queued are signed with the new secret.",
        "x-pl": {
          "summary": "Wymień sekret podpisu",
          "description": "Od razu wymienia sekret podpisu; nowy `secret` jest zwracany tylko tutaj. Wysyłki czekające w kolejce zostaną podpisane nowym sekretem."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookCreated"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "webhooks:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/webhooks/{id}/deliveries": {
      "get": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "listWebhookDeliveries",
        "summary": "List webhook deliveries",
        "description": "Recent attempts (kept 30 days), newest first.",
        "x-pl": {
          "summary": "Lista wysyłek webhooka",
          "description": "Ostatnie próby (przechowywane 30 dni), od najnowszych."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/limit"
          },
          {
            "$ref": "#/components/parameters/cursor"
          },
          {
            "$ref": "#/components/parameters/order"
          },
          {
            "$ref": "#/components/parameters/updated_since"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WebhookDeliveryList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "webhooks:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/tasks": {
      "get": {
        "tags": [
          "Work"
        ],
        "operationId": "listTasks",
        "summary": "List tasks",
        "description": "Open tasks by due time. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista zadań",
          "description": "Otwarte zadania wg terminu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "Whose work: mine, user (with user) or all.",
            "x-pl-description": "Czyja praca: mine, user (z user) albo all.",
            "schema": {
              "type": "string",
              "enum": [
                "mine",
                "user",
                "all"
              ],
              "default": "mine"
            }
          },
          {
            "name": "user",
            "in": "query",
            "required": false,
            "description": "Member id for scope=user.",
            "x-pl-description": "Identyfikator członka dla scope=user.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TaskList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "tasks:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/contacts/{id}/tasks": {
      "post": {
        "tags": [
          "Work"
        ],
        "operationId": "createTask",
        "summary": "Create a task",
        "description": "Adds a task to the person, like „Dodaj zadanie” on the card. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Dodaj zadanie",
          "description": "Dodaje zadanie osobie, jak „Dodaj zadanie” na karcie. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "x-pl-description": "Utworzono",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Created"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "tasks:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskCreate"
              }
            }
          }
        }
      }
    },
    "/tasks/{id}/done": {
      "post": {
        "tags": [
          "Work"
        ],
        "operationId": "completeTask",
        "summary": "Complete a task",
        "description": "Closes the task, optionally with a history entry. Send `{}` for none. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Oznacz zadanie jako zrobione",
          "description": "Zamyka zadanie, opcjonalnie z wpisem w historii. Wyślij `{}`, jeśli bez wpisu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Done",
            "x-pl-description": "Zrobione"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "tasks:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskDone"
              }
            }
          }
        }
      }
    },
    "/tasks/{id}/postpone": {
      "post": {
        "tags": [
          "Work"
        ],
        "operationId": "postponeTask",
        "summary": "Postpone a task",
        "description": "Moves the due time by days or to a date. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Przełóż zadanie",
          "description": "Przesuwa termin o dni albo na datę. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Moved",
            "x-pl-description": "Przełożone"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "tasks:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TaskPostpone"
              }
            }
          }
        }
      }
    },
    "/contacts/search": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "searchContacts",
        "summary": "Search contacts with panel filters",
        "description": "The Klienci list with its filters: values of one filter are alternatives (comma list), filters combine. Every bad value is a 400. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Szukaj osób z filtrami panelu",
          "description": "Lista Klienci z jej filtrami: wartości jednego filtra to alternatywy (lista po przecinku), filtry łączą się. Każda zła wartość to 400. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Name, e-mail or phone.",
            "x-pl-description": "Imię, e-mail albo telefon.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, 1 = first.",
            "x-pl-description": "Strona, 1 = pierwsza.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "People per page: 10, 25 (default), 50 or 100.",
            "x-pl-description": "Osób na stronie: 10, 25 (domyślnie), 50 albo 100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "owner",
            "in": "query",
            "required": false,
            "description": "me, any, none or member ids.",
            "x-pl-description": "me, any, none albo identyfikatory członków.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Status ids or none.",
            "x-pl-description": "Identyfikatory statusów albo none.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "tag",
            "in": "query",
            "required": false,
            "description": "Tag.",
            "x-pl-description": "Tag.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "First source name.",
            "x-pl-description": "Nazwa pierwszego źródła.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "buyer",
            "in": "query",
            "required": false,
            "description": "yes = has a bought shop order, no = none.",
            "x-pl-description": "yes = ma opłacone zamówienie, no = brak.",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "orders_min",
            "in": "query",
            "required": false,
            "description": "At least this many bought orders.",
            "x-pl-description": "Co najmniej tyle opłaconych zamówień.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "orders_max",
            "in": "query",
            "required": false,
            "description": "At most this many bought orders.",
            "x-pl-description": "Najwyżej tyle opłaconych zamówień.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "spent_min",
            "in": "query",
            "required": false,
            "description": "Spent at least.",
            "x-pl-description": "Wydał co najmniej.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "spent_max",
            "in": "query",
            "required": false,
            "description": "Spent at most.",
            "x-pl-description": "Wydał najwyżej.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "last_order",
            "in": "query",
            "required": false,
            "description": "Last purchase within.",
            "x-pl-description": "Ostatni zakup w okresie.",
            "schema": {
              "type": "string",
              "enum": [
                "30d",
                "90d",
                "180d",
                "365d"
              ]
            }
          },
          {
            "name": "inactive_buyer",
            "in": "query",
            "required": false,
            "description": "Bought before but not in the last N days.",
            "x-pl-description": "Kupował, ale nie w ostatnich N dniach.",
            "schema": {
              "type": "string",
              "enum": [
                "30",
                "60",
                "90",
                "180",
                "365"
              ]
            }
          },
          {
            "name": "first_order",
            "in": "query",
            "required": false,
            "description": "First purchase within.",
            "x-pl-description": "Pierwszy zakup w okresie.",
            "schema": {
              "type": "string",
              "enum": [
                "30d",
                "90d"
              ]
            }
          },
          {
            "name": "product",
            "in": "query",
            "required": false,
            "description": "Bought this catalogue id (repeatable).",
            "x-pl-description": "Kupił produkt o tym id (można powtórzyć).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created",
            "in": "query",
            "required": false,
            "description": "today, 7d, 30d or 90d (or created_from / created_to days).",
            "x-pl-description": "today, 7d, 30d albo 90d (albo dni created_from / created_to).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "activity",
            "in": "query",
            "required": false,
            "description": "Last activity: today, 7d, 30d, 90d (or activity_from / activity_to).",
            "x-pl-description": "Ostatnia aktywność: today, 7d, 30d, 90d (albo activity_from / activity_to).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "inactive_days",
            "in": "query",
            "required": false,
            "description": "No activity for at least this many days.",
            "x-pl-description": "Bez aktywności co najmniej tyle dni.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "tasks",
            "in": "query",
            "required": false,
            "description": "open, overdue or none.",
            "x-pl-description": "open, overdue albo none.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "phone",
            "in": "query",
            "required": false,
            "description": "yes or no.",
            "x-pl-description": "yes albo no.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "email",
            "in": "query",
            "required": false,
            "description": "yes or no.",
            "x-pl-description": "yes albo no.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "optout",
            "in": "query",
            "required": false,
            "description": "yes or no.",
            "x-pl-description": "yes albo no.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "duplicate",
            "in": "query",
            "required": false,
            "description": "yes or no.",
            "x-pl-description": "yes albo no.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "activity, activity_asc, created, created_asc, spent, spent_asc, orders, orders_asc, aov (average order), aov_asc, last_order, last_order_asc, first_order or first_order_asc. Ascending purchase sorts put people without orders last.",
            "x-pl-description": "activity, activity_asc, created, created_asc, spent, spent_asc, orders, orders_asc, aov (średnie zamówienie), aov_asc, last_order, last_order_asc, first_order albo first_order_asc. Rosnące sortowania zakupów stawiają osoby bez zamówień na końcu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ContactSearch"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/contact-statuses": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "listContactStatuses",
        "summary": "List statuses",
        "description": "The organisation's internal statuses. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista statusów",
          "description": "Wewnętrzne statusy organizacji. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/contacts/{id}/status": {
      "post": {
        "tags": [
          "Contacts"
        ],
        "operationId": "setContactStatus",
        "summary": "Set the status",
        "description": "Sets an internal status (a history line). Never sent to Meta; status automations start. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Ustaw status",
          "description": "Ustawia status wewnętrzny (wpis w historii). Nigdy nie trafia do Mety; uruchamiają się automatyzacje statusu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResult"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "contacts:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StatusChange"
              }
            }
          }
        }
      }
    },
    "/contacts/{id}/history": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "getContactHistory",
        "summary": "Contact history",
        "description": "Orders, calls, notes, statuses, tasks and SMS of the person. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Historia osoby",
          "description": "Zamówienia, telefony, notatki, statusy, zadania i SMS-y osoby. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, 1 = newest.",
            "x-pl-description": "Strona, 1 = najnowsze.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/History"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/diagnostics": {
      "get": {
        "tags": [
          "Diagnostics"
        ],
        "operationId": "getDiagnostics",
        "summary": "Last self-check",
        "description": "The last self-check run with every check. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Ostatnia autodiagnostyka",
          "description": "Ostatnie uruchomienie autodiagnostyki ze wszystkimi sprawdzeniami. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Diagnostics"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "diagnostics:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/diagnostics/run": {
      "post": {
        "tags": [
          "Diagnostics"
        ],
        "operationId": "runDiagnostics",
        "summary": "Run the self-check",
        "description": "Like „Sprawdź teraz”: queues a run (or starts a waiting one at once). Read the result with GET /diagnostics. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Uruchom autodiagnostykę",
          "description": "Jak „Sprawdź teraz”: dodaje uruchomienie do kolejki (albo od razu startuje czekające). Wynik odczytasz przez GET /diagnostics. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "202": {
            "description": "Queued",
            "x-pl-description": "W kolejce",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DiagnosticsRun"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "diagnostics:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "listProducts",
        "summary": "List products",
        "description": "Active products of the organisation or of one feed, 50 per page (or per_page), with their diagnosis, origin, Google category, fixes, the period's results and a sales trend. Values of one filter OR, filters AND. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista produktów",
          "description": "Aktywne produkty organizacji albo jednego feedu, po 50 na stronę (albo per_page), z diagnozą, pochodzeniem, kategorią Google, poprawkami, wynikami okresu i trendem sprzedaży. Wartości jednego filtra łączy LUB, filtry — I. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "feed",
            "in": "query",
            "required": false,
            "description": "Only products of this feed.",
            "x-pl-description": "Tylko produkty tego feedu.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Title, SKU, exact EAN or exact catalogue id.",
            "x-pl-description": "Tytuł, SKU, dokładny EAN albo dokładny identyfikator katalogowy.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "origin",
            "in": "query",
            "required": false,
            "description": "Comma list of shop source ids or feed ids the products come from (facets.origins).",
            "x-pl-description": "Lista (po przecinku) identyfikatorów źródeł sklepów albo feedów, z których pochodzą produkty (facets.origins).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Shop category, exact; repeat for several (facets.categories).",
            "x-pl-description": "Kategoria sklepu, dokładnie; powtórz dla kilku (facets.categories).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "required": false,
            "description": "Brand, exact; repeat for several (facets.brands).",
            "x-pl-description": "Marka, dokładnie; powtórz dla kilku (facets.brands).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "availability",
            "in": "query",
            "required": false,
            "description": "Comma list of in_stock, out_of_stock, preorder, backorder, unknown.",
            "x-pl-description": "Lista (po przecinku): in_stock, out_of_stock, preorder, backorder, unknown.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "price_min",
            "in": "query",
            "required": false,
            "description": "Lowest price a shopper pays (the sale price when there is one).",
            "x-pl-description": "Najniższa cena dla kupującego (cena promocyjna, jeśli jest).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "price_max",
            "in": "query",
            "required": false,
            "description": "Highest price a shopper pays.",
            "x-pl-description": "Najwyższa cena dla kupującego.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "score_min",
            "in": "query",
            "required": false,
            "description": "Lowest quality score 0–100.",
            "x-pl-description": "Najniższa ocena jakości 0–100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "score_max",
            "in": "query",
            "required": false,
            "description": "Highest quality score 0–100.",
            "x-pl-description": "Najwyższa ocena jakości 0–100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "issue",
            "in": "query",
            "required": false,
            "description": "Comma list of problem codes; any of them matches.",
            "x-pl-description": "Lista kodów problemów (po przecinku); pasuje dowolny.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Comma list of worst problems: error, warning, clean.",
            "x-pl-description": "Lista najgorszych problemów (po przecinku): error, warning, clean.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "fixes",
            "in": "query",
            "required": false,
            "description": "Comma list: auto (Basketly's automatic fixes repair a problem), manual (a person typed a fix), none.",
            "x-pl-description": "Lista (po przecinku): auto (automatyczne poprawki Basketly naprawiają problem), manual (ręczna poprawka), none.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "google",
            "in": "query",
            "required": false,
            "description": "Comma list: set (leaves the feeds with a Google category: a person's, its own or a sure automatic one), review (automatic, confidence under 60), none (Basketly picks one by the title when building the feed).",
            "x-pl-description": "Lista (po przecinku): set (wychodzi z feedów z kategorią Google: wybraną przez człowieka, własną albo pewną automatyczną), review (automatyczna, pewność poniżej 60), none (Basketly dobiera ją po nazwie przy budowie feedu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exposure",
            "in": "query",
            "required": false,
            "description": "Comma list: none = not shown in catalogue ads in the period, low = under 100 impressions (not shown included), shown.",
            "x-pl-description": "Lista (po przecinku): none = bez emisji w reklamach katalogowych w okresie, low = poniżej 100 wyświetleń (razem z bez emisji), shown = pokazywane.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sales",
            "in": "query",
            "required": false,
            "description": "yes = bought in the period, no = not bought.",
            "x-pl-description": "yes = kupowany w okresie, no = niekupowany.",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "title (default), title_desc, score (worst first), score_desc, price, stock, issues, synced, or the period's impressions, clicks, ctr, units, revenue, views — most first; `_asc` = least first.",
            "x-pl-description": "title (domyślnie), title_desc, score (najgorsze najpierw), score_desc, price, stock, issues, synced albo z okresu impressions, clicks, ctr, units, revenue, views — od największych; `_asc` = od najmniejszych.",
            "schema": {
              "type": "string",
              "enum": [
                "title",
                "title_desc",
                "score",
                "score_desc",
                "price",
                "price_asc",
                "stock",
                "stock_asc",
                "issues",
                "issues_asc",
                "synced",
                "synced_asc",
                "impressions",
                "impressions_asc",
                "clicks",
                "clicks_asc",
                "ctr",
                "ctr_asc",
                "units",
                "units_asc",
                "revenue",
                "revenue_asc",
                "views",
                "views_asc"
              ]
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Statistics period: 7, 14, 30 (default) or 90 days.",
            "x-pl-description": "Okres statystyk: 7, 14, 30 (domyślnie) albo 90 dni.",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "14",
                "30",
                "90"
              ]
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Products per page: 10, 25, 50 (default) or 100.",
            "x-pl-description": "Produktów na stronę: 10, 25, 50 (domyślnie) albo 100.",
            "schema": {
              "type": "integer"
            }
          },
          {
            "name": "facets",
            "in": "query",
            "required": false,
            "description": "1 adds `facets`: origins, categories, brands, availability, google and fixes with product counts.",
            "x-pl-description": "1 dodaje `facets`: pochodzenia, kategorie, marki, dostępność, google i poprawki z liczbą produktów.",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, 1 = first.",
            "x-pl-description": "Strona, 1 = pierwsza.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products/performance": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "productsPerformance",
        "summary": "Catalogue performance",
        "description": "Products not shown, barely shown and shown in catalogue ads, best sellers and most shown without a sale. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wyniki katalogu",
          "description": "Produkty bez emisji, ze słabą emisją i pokazywane w reklamach katalogowych, najlepiej sprzedające się i najczęściej pokazywane bez sprzedaży. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Statistics period: 7, 14, 30 (default) or 90 days.",
            "x-pl-description": "Okres statystyk: 7, 14, 30 (domyślnie) albo 90 dni.",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "14",
                "30",
                "90"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductsPerformance"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products/{product}/stats": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "productStats",
        "summary": "Product results",
        "description": "One product in ads (Meta per-product breakdown), in the shop (Basketly script) and in sales (orders), per day. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wyniki produktu",
          "description": "Jeden produkt w reklamach (rozbicie Mety na produkty), w sklepie (skrypt Basketly) i w sprzedaży (zamówienia), dzień po dniu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "description": "Product record id.",
            "x-pl-description": "Identyfikator produktu.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Statistics period: 7, 14, 30 (default) or 90 days.",
            "x-pl-description": "Okres statystyk: 7, 14, 30 (domyślnie) albo 90 dni.",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "14",
                "30",
                "90"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductStats"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products/unseen-flow": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "makeUnseenFlow",
        "summary": "Feed of products not shown",
        "description": "Creates a flow feed of the products catalogue ads showed fewer than `below` times in the last `days` days. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Feed z produktów bez emisji",
          "description": "Tworzy przepływ feedu z produktów, które reklamy katalogowe pokazały mniej niż `below` razy w ostatnich `days` dniach. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UnseenFlow"
              }
            }
          }
        }
      }
    },
    "/products/{product}": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "getProduct",
        "summary": "Get a product",
        "description": "The product record of the panel. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pobierz produkt",
          "description": "Kartoteka produktu z panelu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "description": "Product record id.",
            "x-pl-description": "Identyfikator produktu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products/{product}/overrides": {
      "put": {
        "tags": [
          "Products"
        ],
        "operationId": "setProductOverrides",
        "summary": "Set manual fixes",
        "description": "Values typed by hand win over fixes, rules and flows in every feed. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Ustaw ręczne poprawki",
          "description": "Wartości wpisane ręcznie wygrywają z poprawkami, regułami i przepływami w każdym feedzie. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "description": "Product record id.",
            "x-pl-description": "Identyfikator produktu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Product"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "products:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProductOverrides"
              }
            }
          }
        }
      }
    },
    "/guidelines": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "listGuidelines",
        "summary": "List guidelines",
        "description": "Vendor rules for product data with their sources and how many products break each. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista wytycznych",
          "description": "Zasady dostawców dotyczące danych produktów ze źródłami i liczbą produktów, które łamią każdą. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Guidelines"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/products/{product}/title-suggestions": {
      "post": {
        "tags": [
          "Products"
        ],
        "operationId": "suggestTitles",
        "summary": "Suggest titles",
        "description": "Asks the AI (MiniMax) for 1–3 better titles following the title guidelines; only the product's own attributes are sent, every proposal is rechecked by Basketly's title checks. Nothing is saved. Uses the organisation's daily AI budget (429 when spent, also over 30 calls per hour). Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zaproponuj tytuły",
          "description": "Prosi AI (MiniMax) o 1–3 lepsze tytuły zgodne z wytycznymi tytułów; wysyłane są tylko atrybuty produktu, każdą propozycję sprawdzają ponownie sprawdzenia tytułu Basketly. Nic nie jest zapisywane. Zużywa dzienny budżet AI organizacji (429 po jego wyczerpaniu, także ponad 30 wywołań na godzinę). Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "product",
            "in": "path",
            "required": true,
            "description": "Product record id.",
            "x-pl-description": "Identyfikator produktu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TitleSuggestions"
                }
              }
            }
          },
          "502": {
            "description": "MiniMax did not answer or gave no title that passes the guidelines (`upstream_error`).",
            "x-pl-description": "MiniMax nie odpowiedział albo nie dał tytułu zgodnego z wytycznymi (`upstream_error`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "503": {
            "description": "AI suggestions are off on this server: no MiniMax key (`unavailable`).",
            "x-pl-description": "Sugestie AI są wyłączone na tym serwerze: brak klucza MiniMax (`unavailable`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "products:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/feeds": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "listFeeds",
        "summary": "List feeds",
        "description": "Every feed with its state and output address. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista feedów",
          "description": "Wszystkie feedy ze stanem i adresem wyjścia. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "createFeed",
        "summary": "Create a feed",
        "description": "Like „Dodaj feed”: from an address (download queued), a shop, other feeds or as a flow (starts with the chosen feeds joined in the output, or with a whole canvas). Uploading a file stays in the panel. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Dodaj feed",
          "description": "Jak „Dodaj feed”: z adresu (pobieranie w kolejce), ze sklepu, z innych feedów albo jako przepływ (startuje z wybranymi feedami połączonymi w wyjściu albo z całym płótnem). Wgrywanie pliku zostaje w panelu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedCreate"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getFeed",
        "summary": "Get a feed",
        "description": "A feed with its attributes; a flow with its canvas. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pobierz feed",
          "description": "Feed z atrybutami; przepływ z płótnem. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Feeds"
        ],
        "operationId": "updateFeed",
        "summary": "Update a feed",
        "description": "Name, address, download interval, automatic fixes, parents, output format, link tagging (fields of link_tagging left out stay). Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zmień feed",
          "description": "Nazwa, adres, częstotliwość pobierania, automatyczne poprawki, źródła, format wyjścia, tagowanie linków (pominięte pola link_tagging zostają). Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedUpdate"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}/link-tagging/preview": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "previewLinkTagging",
        "summary": "Preview link tagging",
        "description": "Tags one served product's links with a draft setting (fields left out = the saved ones). Nothing is saved. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Podgląd tagowania linków",
          "description": "Taguje linki jednego produktu z feedu szkicem ustawienia (pominięte pola = zapisane). Nic nie jest zapisywane. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LinkTaggingPreview"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LinkTagging"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}/rules": {
      "put": {
        "tags": [
          "Feeds"
        ],
        "operationId": "setFeedRules",
        "summary": "Save feed rules",
        "description": "Replaces the rules of a feed (not a flow); the served feed uses them at once. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zapisz reguły feedu",
          "description": "Zastępuje reguły feedu (nie przepływu); feed wyjściowy używa ich od razu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedRules"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}/flow": {
      "put": {
        "tags": [
          "Feeds"
        ],
        "operationId": "setFeedFlow",
        "summary": "Save a feed flow",
        "description": "Replaces the canvas of a flow; the served feed and its format follow at once. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zapisz przepływ feedu",
          "description": "Zastępuje płótno przepływu; feed wyjściowy i jego format zmieniają się od razu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedFlow"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}/preview": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "previewFeed",
        "summary": "Preview a feed",
        "description": "Runs unsaved rules or an unsaved canvas over every product and returns what would change. Nothing is saved. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Podgląd feedu",
          "description": "Uruchamia niezapisane reguły albo niezapisane płótno na wszystkich produktach i zwraca, co by się zmieniło. Nic nie jest zapisywane. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedPreview"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedPreviewRequest"
              }
            }
          }
        }
      }
    },
    "/feeds/{id}/fetch": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "fetchFeed",
        "summary": "Download now",
        "description": "Queues a download of the feed (feeds made from feeds and flows: of their inputs). Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pobierz teraz",
          "description": "Dodaje pobranie feedu do kolejki (feedy z feedów i przepływy: ich wejść). Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "204": {
            "description": "Queued",
            "x-pl-description": "W kolejce"
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Unprocessable"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/feeds/{id}/categories": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getFeedCategories",
        "summary": "Feed categories",
        "description": "Shop categories with the Google category each gets — a person's, chosen automatically with its confidence, or by each product's title — and suggestions. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Kategorie feedu",
          "description": "Kategorie sklepu z kategorią Google, którą dostaje każda — wybraną przez człowieka, automatycznie z pewnością albo po nazwie każdego produktu — i podpowiedziami. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedCategories"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "put": {
        "tags": [
          "Feeds"
        ],
        "operationId": "setFeedCategories",
        "summary": "Save feed categories",
        "description": "Saves the Google category and own name per shop category; entries without auto are a person's and win over the automatic choice. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zapisz kategorie feedu",
          "description": "Zapisuje kategorię Google i własną nazwę dla każdej kategorii sklepu; pozycje bez auto są wyborem człowieka i wygrywają z automatycznym. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Feed"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "413": {
            "$ref": "#/components/responses/TooLarge"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedCategoriesSave"
              }
            }
          }
        }
      },
      "patch": {
        "tags": [
          "Feeds"
        ],
        "operationId": "changeFeedCategories",
        "summary": "Change some feed categories",
        "description": "Changes only the named rows: a person's Google category, confirming the automatic one, back to automatic, own name. Answers with the changed rows and the summary of all rows. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zmień wybrane kategorie feedu",
          "description": "Zmienia tylko podane wiersze: kategoria Google człowieka, zatwierdzenie automatycznej, powrót do automatycznej, własna nazwa. Odpowiada zmienionymi wierszami i podsumowaniem wszystkich. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedCategories"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/FeedCategoriesChange"
              }
            }
          }
        }
      }
    },
    "/google-categories": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "searchGoogleCategories",
        "summary": "Search Google categories",
        "description": "Finds categories of Google's product taxonomy by Polish or English words or by id (for the `google` of feed categories). Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Szukaj kategorii Google",
          "description": "Znajduje kategorie taksonomii produktów Google po słowach polskich lub angielskich albo po numerze (do pola `google` kategorii feedu). Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Words or a category id, up to 100 characters.",
            "x-pl-description": "Słowa albo numer kategorii, do 100 znaków.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoogleCategories"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/google-taxonomy": {
      "get": {
        "tags": [
          "Feeds"
        ],
        "operationId": "getGoogleTaxonomy",
        "summary": "Google taxonomy version",
        "description": "Which version of Google's product taxonomy Basketly uses, how many categories it has and when Google was last checked (weekly by itself). Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wersja taksonomii Google",
          "description": "Której wersji taksonomii produktów Google używa Basketly, ile ma kategorii i kiedy ostatnio sprawdzono u Google (co tydzień samo). Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoogleTaxonomy"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "feeds:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/google-taxonomy/refresh": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "refreshGoogleTaxonomy",
        "summary": "Check Google taxonomy now",
        "description": "Queues a background job that downloads Google's taxonomy (Polish and English) and puts a valid newer version in use. Owner or admin of the organisation only. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Sprawdź taksonomię Google teraz",
          "description": "Dodaje zadanie w tle, które pobiera taksonomię Google (polską i angielską) i włącza poprawną nowszą wersję. Tylko właściciel albo administrator organizacji. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "202": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GoogleTaxonomy"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/feeds/{id}/categories/auto": {
      "post": {
        "tags": [
          "Feeds"
        ],
        "operationId": "recalculateFeedCategories",
        "summary": "Recalculate automatic categories",
        "description": "Chooses the Google category of every shop category a person has not chosen again (Basketly does it by itself after every product read; this redoes the existing choices too). A person's choices stay. Answers like GET. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Przelicz kategorie automatycznie",
          "description": "Wybiera od nowa kategorię Google każdej kategorii sklepu, której nie wybrał człowiek (Basketly robi to sam po każdym odczycie produktów; to przelicza także istniejące wybory). Wybory ludzi zostają. Odpowiada jak GET. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedCategories"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "feeds:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/sales": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "salesReport",
        "summary": "Sales report",
        "description": "The shop's sales of a period next to the previous one: orders, revenue in the main currency, average order, buyers new/returning, Meta spend, purchases, ROAS, MER, spend per order, purchases accepted for sending, Google Ads / Microsoft Ads spend as each reports it, per day, the top 10 products and `verdict` — one sentence about the period (start here when reading Raporty). Sources are never mixed. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Raport sprzedaży",
          "description": "Sprzedaż sklepu w okresie obok poprzedniego: zamówienia, przychód w głównej walucie, średnie zamówienie, kupujący nowi/powracający, wydatki w Mecie, zakupy, ROAS, MER, wydatki na zamówienie, zakupy przyjęte do wysyłki, wydatki w Google Ads / Microsoft Ads według ich raportów, dzień po dniu, 10 najlepszych produktów i `verdict` — jedno zdanie o okresie (od niego zacznij czytanie Raportów). Źródła nigdy nie są łączone. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SalesReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/channels": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "shopChannels",
        "summary": "Channels and the shop",
        "description": "Every channel of the period next to the shop: blended spend, MER and cost per order over all channels, each channel's figures as its platform reports them (never added across platforms), Basketly's last-click orders per source (shares add up to 100%), the sum of the platforms' own conversions next to the shop's orders, per day revenue and spend per channel — Raporty → Sprzedaż. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Kanały i sklep",
          "description": "Każdy kanał w okresie obok sklepu: łączne wydatki, MER i koszt zamówienia ze wszystkich kanałów, liczby każdego kanału według jego platformy (nigdy nie sumowane między platformami), zamówienia Basketly z ostatniego kliknięcia na źródło (udziały sumują się do 100%), suma własnych konwersji platform obok zamówień sklepu, dzień po dniu przychód i wydatki na kanał — Raporty → Sprzedaż. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelTotals"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/product-channels": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "productChannels",
        "summary": "Products × channels",
        "description": "Every product against every channel that shows it — Raporty → Kanały × produkty: per channel impressions, clicks, spend, CTR and the platform's own per-product conversions where the platform reports them (Meta does not: null), Basketly's last-click orders containing the product, units per 100 clicks and the channel's impression share; the shop's units, revenue, views, carts, stock and days of cover; best channel, spend split and source split. Never adds platform conversions together. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Kanały × produkty",
          "description": "Każdy produkt wobec każdego kanału, który go pokazuje — Raporty → Kanały × produkty: na kanał wyświetlenia, kliknięcia, wydatki, CTR i własne konwersje platformy na produkt tam, gdzie je podaje (Meta nie: null), zamówienia Basketly z ostatniego kliknięcia zawierające produkt, sztuki na 100 kliknięć i udział w wyświetleniach kanału; sztuki, przychód, odsłony, koszyki, stan i dni zapasu sklepu; najlepszy kanał, podział wydatków i źródeł. Nigdy nie sumuje konwersji platform. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Only products with figures in this channel; spend and orders sorting read it.",
            "x-pl-description": "Tylko produkty z liczbami w tym kanale; sortowanie po wydatkach i zamówieniach czyta ten kanał.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "google_ads",
                "microsoft_ads",
                "tiktok",
                "pinterest",
                "openai_ads"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort order (add _asc for ascending).",
            "x-pl-description": "Kolejność (końcówka _asc = rosnąco).",
            "schema": {
              "type": "string",
              "enum": [
                "spend",
                "orders",
                "best",
                "units",
                "revenue",
                "spend_asc",
                "orders_asc",
                "best_asc",
                "units_asc",
                "revenue_asc"
              ],
              "default": "spend"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page from 1.",
            "x-pl-description": "Strona od 1.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Rows per page: 10, 25, 50 or 100.",
            "x-pl-description": "Wierszy na stronę: 10, 25, 50 albo 100.",
            "schema": {
              "type": "string",
              "default": "50"
            }
          },
          {
            "name": "content_id",
            "in": "query",
            "required": false,
            "description": "One product by its catalogue id.",
            "x-pl-description": "Jeden produkt po identyfikatorze z katalogu.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductChannels"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/channels/report": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "channelReport",
        "summary": "Channel report",
        "description": "Without `channel` every channel's totals (Kampanie → Wszystkie kanały); with `channel` that channel's campaigns (ad groups, ads where read) with the platform's figures and Basketly's last-click orders — one vocabulary for Meta, Google Ads, Microsoft Ads, TikTok and Pinterest. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Raport kanału",
          "description": "Bez `channel` sumy każdego kanału (Kampanie → Wszystkie kanały); z `channel` kampanie tego kanału (grupy reklam, reklamy, gdzie odczytane) z liczbami platformy i zamówieniami Basketly z ostatniego kliknięcia — jeden słownik dla Mety, Google Ads, Microsoft Ads, TikToka i Pinteresta. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "One paid channel; empty = every channel's totals.",
            "x-pl-description": "Jeden kanał płatny; puste = sumy wszystkich kanałów.",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "google_ads",
                "microsoft_ads",
                "tiktok",
                "pinterest",
                "openai_ads"
              ]
            }
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "description": "Row level.",
            "x-pl-description": "Poziom wierszy.",
            "schema": {
              "type": "string",
              "enum": [
                "campaign",
                "adgroup",
                "ad"
              ],
              "default": "campaign"
            }
          },
          {
            "name": "parent",
            "in": "query",
            "required": false,
            "description": "The campaign of ad groups / the ad group of ads.",
            "x-pl-description": "Kampania grup reklam / grupa reklam reklam.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ChannelReport"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/manual-spend": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "listManualSpend",
        "summary": "Costs outside ad platforms",
        "description": "Costs the team typed in (comparison sites, e-mail tool, agency, other) per month. Each month's amount is spread evenly over its days and counted in the blended spend, MER and cost per order (GET /reports/channels: lines with `manual`), never as a platform's figures. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Koszty spoza platform reklamowych",
          "description": "Koszty wpisane przez zespół (porównywarki, narzędzie e-mail, agencja, inne) na miesiąc. Kwota miesiąca rozkłada się równo na jego dni i wchodzi do łącznych wydatków, MER i kosztu zamówienia (GET /reports/channels: wiersze z `manual`), nigdy do liczb platformy. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManualSpendList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      },
      "post": {
        "tags": [
          "Reports"
        ],
        "operationId": "createManualSpend",
        "summary": "Add a cost outside ad platforms",
        "description": "Adds one month's cost. Nothing is sent anywhere; only the blended spend and MER change. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Dodaj koszt spoza platform reklamowych",
          "description": "Dodaje koszt jednego miesiąca. Nic nie jest wysyłane; zmieniają się tylko łączne wydatki i MER. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "x-pl-description": "Utworzono",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManualSpend"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualSpendInput"
              }
            }
          }
        }
      }
    },
    "/manual-spend/{id}": {
      "patch": {
        "tags": [
          "Reports"
        ],
        "operationId": "updateManualSpend",
        "summary": "Change a cost outside ad platforms",
        "description": "Changes any field of one entry. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zmień koszt spoza platform reklamowych",
          "description": "Zmienia dowolne pole jednego wpisu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManualSpend"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "campaigns:write",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ManualSpendChange"
              }
            }
          }
        }
      },
      "delete": {
        "tags": [
          "Reports"
        ],
        "operationId": "deleteManualSpend",
        "summary": "Remove a cost outside ad platforms",
        "description": "Removes one entry for good. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Usuń koszt spoza platform reklamowych",
          "description": "Usuwa jeden wpis na stałe. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ManualSpendDeleted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "campaigns:write",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/insights": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "reportInsights",
        "summary": "Report conclusions",
        "description": "Every rule-based conclusion of the period (sales, product trajectories, product magnets, stock, tagged feeds) with the numbers behind it and a suggested action, most important first. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wnioski z raportów",
          "description": "Wszystkie wnioski okresu z reguł (sprzedaż, trajektorie produktów, produkty-magnesy, zatowarowanie, otagowane feedy) z liczbami i proponowanym działaniem, najważniejsze pierwsze. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "channel",
            "in": "query",
            "required": false,
            "description": "Only conclusions about this channel (the `channels` counts still cover every conclusion).",
            "x-pl-description": "Tylko wnioski o tym kanale (liczniki `channels` nadal obejmują wszystkie wnioski).",
            "schema": {
              "type": "string",
              "enum": [
                "meta",
                "google_ads",
                "microsoft_ads",
                "tiktok",
                "pinterest",
                "email",
                "comparison",
                "other",
                "direct",
                "unknown"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReportInsights"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/insights/{key}": {
      "put": {
        "tags": [
          "Reports"
        ],
        "operationId": "setInsightState",
        "summary": "Mark a conclusion",
        "description": "Marks one conclusion for the key's creator only, like the ⋯ menu on Raporty: done, snoozed until a day, dismissed (does not apply) or open again. Other members keep seeing it; repeating the same state changes nothing. It changes no organisation data, so the read scope of the reports is enough. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Oznacz wniosek",
          "description": "Oznacza jeden wniosek tylko dla twórcy klucza, jak menu ⋯ w Raportach: zrobione, odłożone do dnia, nie dotyczy albo znów otwarte. Inni członkowie nadal go widzą; powtórzenie tego samego stanu niczego nie zmienia. Nie zmienia danych organizacji, więc wystarcza uprawnienie do odczytu raportów. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "description": "The conclusion's `key` from GET /reports/insights.",
            "x-pl-description": "Klucz wniosku (`key`) z GET /reports/insights.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InsightState"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InsightStateChange"
              }
            }
          }
        }
      }
    },
    "/reports/products": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "productTrajectories",
        "summary": "Product trajectories",
        "description": "Each product's impressions, clicks and spend in Meta catalogue ads next to its units and revenue from shop orders, day by day (week by week above 31 days), with trends, week-over-week change, pattern and conclusions — every product with impressions, units or views in the period (up to 5000), searched, filtered, sorted and paged on the server (`total`, `listed`, `matched`, `capped`). Clicks and sales are side by side, not attributed. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Trajektorie produktów",
          "description": "Wyświetlenia, kliknięcia i wydatki produktu w reklamach katalogowych Mety obok sprzedanych sztuk i przychodu z zamówień sklepu, dzień po dniu (powyżej 31 dni tydzień po tygodniu), z trendami, zmianą tydzień do tygodnia, wzorcem i wnioskami — każdy produkt z wyświetleniami, sprzedażą albo odsłonami w okresie (do 5000), szukany, filtrowany, sortowany i stronicowany na serwerze (`total`, `listed`, `matched`, `capped`). Kliknięcia i sprzedaż stoją obok siebie, bez atrybucji. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "bucket",
            "in": "query",
            "required": false,
            "description": "day or week (default: day up to 31 days, week above).",
            "x-pl-description": "day albo week (domyślnie day do 31 dni, powyżej week).",
            "schema": {
              "type": "string",
              "enum": [
                "day",
                "week"
              ]
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Text in the product's title or catalogue id; searches every product of the period, not only the first page.",
            "x-pl-description": "Tekst w nazwie albo identyfikatorze produktu; szuka we wszystkich produktach okresu, nie tylko na pierwszej stronie.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "pattern",
            "in": "query",
            "required": false,
            "description": "Only these patterns (repeat or separate with commas); `patterns` in the answer still counts every product.",
            "x-pl-description": "Tylko te wzorce (powtórz albo rozdziel przecinkami); `patterns` w odpowiedzi nadal liczy wszystkie produkty.",
            "schema": {
              "type": "string",
              "enum": [
                "clicks_up_sales_flat",
                "sales_rising",
                "interest_without_sales",
                "both_rising",
                "sales_without_ads",
                "sales_falling",
                "both_falling",
                "clicks_falling",
                "steady",
                "thin"
              ]
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Sort order (add _asc for ascending).",
            "x-pl-description": "Kolejność (końcówka _asc = rosnąco).",
            "schema": {
              "type": "string",
              "enum": [
                "impressions",
                "clicks",
                "ctr",
                "spend",
                "units",
                "revenue",
                "clicks_trend",
                "units_trend",
                "name",
                "impressions_asc",
                "clicks_asc",
                "ctr_asc",
                "spend_asc",
                "units_asc",
                "revenue_asc",
                "clicks_trend_asc",
                "units_trend_asc",
                "name_asc"
              ],
              "default": "impressions"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page from 1.",
            "x-pl-description": "Strona od 1.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Products per page, 1–500.",
            "x-pl-description": "Produktów na stronę, 1–500.",
            "schema": {
              "type": "string",
              "default": "150"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductTrajectories"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/products/detail": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "productTrajectory",
        "summary": "Product trajectory",
        "description": "One product's trajectory, every day of the period, with its conclusions. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Trajektoria produktu",
          "description": "Trajektoria jednego produktu, każdy dzień okresu, z jego wnioskami. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "id",
            "in": "query",
            "required": true,
            "description": "Catalogue product id (content_id).",
            "x-pl-description": "Identyfikator produktu z katalogu (content_id).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductTrajectory"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/magnets": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "productMagnets",
        "summary": "Product magnets",
        "description": "Products people look at or click but rarely buy while the same people buy other products — from linked visits of the shop script and from orders of catalogue ads. Co-occurrence, not proof of cause. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Produkty-magnesy",
          "description": "Produkty, które ludzie oglądają albo klikają, ale rzadko kupują, a ci sami ludzie kupują inne produkty — z powiązanych wizyt skryptu sklepu i z zamówień z reklam katalogowych. Współwystępowanie, nie dowód przyczyny. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductMagnets"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/unseen": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "unseenProducts",
        "summary": "Products not shown",
        "description": "Products in the catalogue (a Basketly feed Meta reads, or every active product without one), available and without Meta errors, that Meta catalogue ads did not show in the period — with the reason, days in the feed, shop demand and stock value. One page of the list; summary and conclusions cover the whole catalogue. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Produkty niewyświetlane",
          "description": "Produkty w katalogu (feed Basketly czytany przez Metę albo, bez niego, każdy aktywny produkt), dostępne i bez błędów Mety, których reklamy katalogowe nie pokazały w okresie — z przyczyną, dniami w feedzie, popytem w sklepie i wartością zapasu. Jedna strona listy; podsumowanie i wnioski obejmują cały katalog. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "reason",
            "in": "query",
            "required": false,
            "description": "Comma list: not_in_feed, excluded_by_rule, out_of_stock, meta_error_check, meta_rejected, meta_pending, pending_sync, not_in_active_set, not_picked.",
            "x-pl-description": "Lista po przecinku: not_in_feed, excluded_by_rule, out_of_stock, meta_error_check, meta_rejected, meta_pending, pending_sync, not_in_active_set, not_picked.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "exposure",
            "in": "query",
            "required": false,
            "description": "Comma list of none, low, shown (default none,low).",
            "x-pl-description": "Lista po przecinku: none, low, shown (domyślnie none,low).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "eligible",
            "in": "query",
            "required": false,
            "description": "yes or no.",
            "x-pl-description": "yes albo no.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "feed",
            "in": "query",
            "required": false,
            "description": "Feed id: products served or left out by it.",
            "x-pl-description": "Id feedu: produkty przez niego serwowane albo pominięte.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Shop category, exact (repeatable).",
            "x-pl-description": "Kategoria sklepu, dokładnie (można powtórzyć).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "required": false,
            "description": "Brand, exact (repeatable).",
            "x-pl-description": "Marka, dokładnie (można powtórzyć).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "availability",
            "in": "query",
            "required": false,
            "description": "Comma list: in_stock, out_of_stock, preorder, backorder, unknown.",
            "x-pl-description": "Lista po przecinku: in_stock, out_of_stock, preorder, backorder, unknown.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sales",
            "in": "query",
            "required": false,
            "description": "yes or no: units sold in the period.",
            "x-pl-description": "yes albo no: sprzedane sztuki w okresie.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "views",
            "in": "query",
            "required": false,
            "description": "yes or no: shop views in the period.",
            "x-pl-description": "yes albo no: odsłony w sklepie w okresie.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Title, SKU or catalogue id.",
            "x-pl-description": "Tytuł, SKU albo id z katalogu.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "stock_value (default), units, views, revenue, impressions, days_in_feed, last_impression, title; _asc reverses.",
            "x-pl-description": "stock_value (domyślnie), units, views, revenue, impressions, days_in_feed, last_impression, title; _asc odwraca.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, from 1.",
            "x-pl-description": "Strona, od 1.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "10, 25 (default), 50 or 100.",
            "x-pl-description": "10, 25 (domyślnie), 50 albo 100.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UnseenProducts"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/stock-ads": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "stockAds",
        "summary": "Sold out but shown",
        "description": "Products with impressions and spend on days the shop said out of stock (from the availability changes of the nightly product reads), the catalogue's lag, and products back in stock for at least 3 days without an impression since. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wyprzedane z emisją",
          "description": "Produkty z wyświetleniami i wydatkami w dniach, gdy sklep podawał brak towaru (ze zmian dostępności z nocnych odczytów produktów), opóźnienie katalogu oraz produkty, które wróciły na stan co najmniej 3 dni temu i od tego czasu nie miały wyświetleń. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StockAds"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/concentration": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "deliveryConcentration",
        "summary": "Delivery concentration",
        "description": "How unevenly Meta spreads catalogue-ad impressions over the products of a scope (all, ad account, campaign, ad set or ad): rank table, top shares, Gini, HHI and effective products, weekly series, before/after sell-outs of top products and conclusions. Meta purchases only for the whole scope, never per product. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Koncentracja emisji",
          "description": "Jak nierówno Meta rozkłada wyświetlenia reklam katalogowych na produkty zakresu (wszystko, konto reklamowe, kampania, zestaw albo reklama): ranking, udziały czołówki, Gini, HHI i efektywna liczba produktów, seria tygodniowa, okresy przed i po wyprzedaniu produktów z czołówki oraz wnioski. Zakupy z Mety tylko dla całego zakresu, nigdy na produkt. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "scope",
            "in": "query",
            "required": false,
            "description": "all (default), account, campaign, adset or ad.",
            "x-pl-description": "all (domyślnie), account, campaign, adset albo ad.",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "account",
                "campaign",
                "adset",
                "ad"
              ]
            }
          },
          {
            "name": "id",
            "in": "query",
            "required": false,
            "description": "Id of the ad account (act_…), campaign, ad set or ad; required unless scope=all. The answer's `options` list them.",
            "x-pl-description": "Identyfikator konta reklamowego (act_…), kampanii, zestawu albo reklamy; wymagany poza scope=all. Lista w `options` odpowiedzi.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/DeliveryConcentration"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/stock": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "stockSignals",
        "summary": "Stock signals",
        "description": "Which products run out before a restock can arrive: velocity of the last 7/14/28 days, days of cover, stockout date, reorder point, suggested quantity, level against the lead time and demand from catalogue ads and the shop script. Stock is the shop's number at the last read, plus Basketly's labelled estimate; the forecast is linear. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Sygnały zatowarowania",
          "description": "Które produkty skończą się przed dostawą: tempo sprzedaży z 7/14/28 dni, dni zapasu, data braku towaru, punkt zamówienia, sugerowana ilość, poziom względem czasu dostawy i popyt z reklam katalogowych i skryptu sklepu. Stan to liczba ze sklepu z ostatniego odczytu plus podpisany szacunek Basketly; prognoza jest liniowa. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "level",
            "in": "query",
            "required": false,
            "description": "Comma list: sold_out, critical, warning, watch, ok, overstock, thin.",
            "x-pl-description": "Lista po przecinku: sold_out, critical, warning, watch, ok, overstock, thin.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "rising",
            "in": "query",
            "required": false,
            "description": "1 = only products with rising clicks or carts.",
            "x-pl-description": "1 = tylko produkty z rosnącymi kliknięciami albo koszykami.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "in_ads",
            "in": "query",
            "required": false,
            "description": "1 = only products with impressions in the last 7 days.",
            "x-pl-description": "1 = tylko produkty z wyświetleniami w ostatnich 7 dniach.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "brand",
            "in": "query",
            "required": false,
            "description": "Only this brand.",
            "x-pl-description": "Tylko ta marka.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category",
            "in": "query",
            "required": false,
            "description": "Category contains this text.",
            "x-pl-description": "Kategoria zawiera ten tekst.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Shop kind or feed.",
            "x-pl-description": "Rodzaj sklepu albo feed.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "lead_time",
            "in": "query",
            "required": false,
            "description": "What-if lead time in days (1–180); default: the organisation's setting.",
            "x-pl-description": "Czas dostawy do symulacji w dniach (1–180); domyślnie ustawienie organizacji.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StockSignals"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/feed-orders": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "feedOrders",
        "summary": "Orders from tagged feeds",
        "description": "Orders whose visit landed on a tagged catalogue link, per feed and per landing product, with orders per 100 clicks of the feed's products. Basketly's own reading from the shop script (needs link tagging and the script), not Meta's purchases. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zamówienia z otagowanych feedów",
          "description": "Zamówienia, których wizyta trafiła przez otagowany link katalogu, na feed i na produkt wejścia, z zamówieniami na 100 kliknięć produktów feedu. Własny odczyt Basketly ze skryptu sklepu (wymaga oznaczania linków i skryptu), nie zakupy według Mety. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/FeedOrders"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/reports/product-sets": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "productSetHealth",
        "summary": "Product set health",
        "description": "Per product set of the chosen Meta catalogues: product count, share in stock, approved, rejected and pending, spend of the ad sets promoting it and warnings; plus Meta's catalogue diagnostics. Needs the optional catalogue connection (catalog_management); without it `connected` is false and the lists are empty. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Zdrowie zestawów produktów",
          "description": "Dla każdego zestawu produktów wybranych katalogów Meta: liczba produktów, udział dostępnych, zatwierdzonych, odrzuconych i oczekujących, wydatki zestawów reklam, które go promują, i ostrzeżenia; do tego diagnostyka katalogu Mety. Wymaga opcjonalnego połączenia katalogu (catalog_management); bez niego `connected` jest false, a listy są puste. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (do 366 dni).",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductSetHealth"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/meta-catalog": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "metaCatalogState",
        "summary": "Meta catalogue connection",
        "description": "Whether the organisation connected a Meta catalogue (optional), which catalogues it chose and how their last read went. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Połączenie katalogu Meta",
          "description": "Czy organizacja połączyła katalog Meta (opcjonalnie), które katalogi wybrała i jak poszedł ich ostatni odczyt. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaCatalogState"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/meta-catalog/status": {
      "get": {
        "tags": [
          "Products"
        ],
        "operationId": "metaCatalogStatus",
        "summary": "Catalogue status of products",
        "description": "For up to 500 content ids: review status, availability, visibility and product set membership in the chosen Meta catalogues, with the catalogue reason the product gets no delivery. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Status produktów w katalogu",
          "description": "Dla najwyżej 500 identyfikatorów produktów: status weryfikacji, dostępność, widoczność i przynależność do zestawów produktów w wybranych katalogach Meta, z powodem z katalogu, dla którego produkt nie ma emisji. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "content_ids",
            "in": "query",
            "required": true,
            "description": "Comma list of content ids (catalogue retailer_id), at most 500.",
            "x-pl-description": "Lista identyfikatorów produktów (retailer_id w katalogu) po przecinku, najwyżej 500.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MetaCatalogStatus"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "products:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/automations": {
      "get": {
        "tags": [
          "Automations"
        ],
        "operationId": "listAutomations",
        "summary": "List automations",
        "description": "The organisation's automations: name, on/off, trigger type, version, author, last run, failed steps of the last 24 hours, runs, sends and failed steps of the last 30 days, runs in progress and what each can send. Editing and switching stay in the panel. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista automatyzacji",
          "description": "Automatyzacje organizacji: nazwa, włączona/wyłączona, rodzaj wyzwalacza, wersja, autor, ostatnie uruchomienie, błędne kroki z ostatnich 24 godzin, uruchomienia, wysyłki i błędne kroki z ostatnich 30 dni, uruchomienia w toku i co każda może wysłać. Edycja i włączanie zostają w panelu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/AutomationList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "automations:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/segments": {
      "get": {
        "tags": [
          "Contacts"
        ],
        "operationId": "listSegments",
        "summary": "List segments",
        "description": "Saved customer segments (Klienci filters with a name) and the ready-made shop segments, each with the number of people the member may see and, for saved ones, the Meta audience and Klaviyo list state. A segment's `filters` are /contacts/search parameters. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista segmentów",
          "description": "Zapisane segmenty klientów (filtry Klientów z nazwą) i gotowe segmenty sklepu, każdy z liczbą osób widocznych dla członka i — dla zapisanych — stanem grupy odbiorców Meta i listy Klaviyo. `filters` segmentu to parametry /contacts/search. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SegmentList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "contacts:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/conversions/balance": {
      "get": {
        "tags": [
          "Events"
        ],
        "operationId": "conversionBalance",
        "summary": "Purchase balance",
        "description": "Day by day: the shop's bought orders, purchase events Basketly accepted and, per destination (each Meta receiver, GA4, TikTok, Google Ads, Microsoft Ads, Pinterest, Klaviyo — Klaviyo gets only purchases with an e-mail), purchases accepted, failed and waiting, with the most common failure reasons. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Bilans zakupów",
          "description": "Dzień po dniu: opłacone zamówienia sklepu, zakupy przyjęte przez Basketly i na każde miejsce docelowe (odbiorca Meta, GA4, TikTok, Google Ads, Microsoft Ads, Pinterest, Klaviyo — do Klaviyo tylko zakupy z e-mailem) zakupy przyjęte, z błędem i czekające, z najczęstszymi powodami błędów. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "days",
            "in": "query",
            "required": false,
            "description": "Period: 7, 14, 30 (default) or 90 days.",
            "x-pl-description": "Okres: 7, 14, 30 (domyślnie) albo 90 dni.",
            "schema": {
              "type": "string",
              "enum": [
                "7",
                "14",
                "30",
                "90"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ConversionBalance"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "events:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/integrations": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "operationId": "listIntegrations",
        "summary": "List integrations",
        "description": "Every place the shop connects, by category, with its state; connecting stays in the panel. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista integracji",
          "description": "Wszystkie miejsca, z którymi łączy się sklep, według kategorii, ze stanem; łączenie zostaje w panelu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Integrations"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "integrations:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/getting-started": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "operationId": "gettingStarted",
        "summary": "Getting started",
        "description": "The organisation's setup checklist: shop connected, Meta receiver, a running flow to Meta, a product feed, a Meta ad account read, other platforms (optional) — each with its state counted from the organisation's records and the panel address where it is done. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pierwsze kroki",
          "description": "Lista pierwszych kroków organizacji: podłączony sklep, odbiorca Meta, działający przepływ do Meta, feed produktowy, odczytane konto reklamowe Meta, inne platformy (opcjonalnie) — każdy ze stanem liczonym z danych organizacji i adresem w panelu, w którym się go wykonuje. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/GettingStarted"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "integrations:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/map": {
      "get": {
        "tags": [
          "Integrations"
        ],
        "operationId": "setupMap",
        "summary": "Connection map",
        "description": "The whole shop setup read-only: where data comes from (shop sources, feeds, logins), what Basketly does with it (orders, products, conversions, segments, automations, templates) and where it goes (Meta receivers, GA4/TikTok/Pinterest/Klaviyo, Meta audiences and Klaviyo lists, feed formats, API, agents), with the health of every node and edge. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Mapa połączeń",
          "description": "Cała konfiguracja sklepu tylko do odczytu: skąd przychodzą dane (źródła sklepu, feedy, logowania), co robi z nimi Basketly (zamówienia, produkty, konwersje, segmenty, automatyzacje, szablony) i dokąd trafiają (odbiorcy Meta, GA4/TikTok/Pinterest/Klaviyo, grupy odbiorców Meta i listy Klaviyo, formaty feedów, API, agenci), ze stanem każdego elementu i połączenia. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SetupMap"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "integrations:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/orders": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "listOrders",
        "summary": "List orders",
        "description": "Shop orders of a period (days in the organisation's zone, default the last 30), bought by default, with the Zamówienia filters and sorts. Values of one filter mean any of them, filters combine; a wrong value is a 400. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista zamówień",
          "description": "Zamówienia ze sklepu z okresu (dni w strefie organizacji, domyślnie ostatnie 30), domyślnie kupione, z filtrami i sortowaniem listy Zamówienia. Kilka wartości jednego filtra = dowolna z nich, filtry łączą się; błędna wartość to 400. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD.",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD (range up to 366 days).",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD (zakres do 366 dni).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Which orders: bought (default), unpaid, cancelled or all; a comma list means any of them.",
            "x-pl-description": "Które zamówienia: bought (domyślnie), unpaid, cancelled albo all; lista po przecinku = dowolny z nich.",
            "schema": {
              "type": "string",
              "default": "bought"
            }
          },
          {
            "name": "contact",
            "in": "query",
            "required": false,
            "description": "Orders of this person (all dates unless from/to are given).",
            "x-pl-description": "Zamówienia tej osoby (wszystkie daty, jeśli nie podano from/to).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "required": false,
            "description": "Order number fragment, or the buyer's full e-mail or phone (matched by hash).",
            "x-pl-description": "Fragment numeru zamówienia albo pełny e-mail lub telefon kupującego (dopasowanie po skrócie).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "source",
            "in": "query",
            "required": false,
            "description": "Comma list of shop source ids (facets.sources).",
            "x-pl-description": "Lista identyfikatorów źródeł sklepu po przecinku (facets.sources).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "shop_status",
            "in": "query",
            "required": false,
            "description": "The shop's own status name; repeat for several (facets.shop_statuses).",
            "x-pl-description": "Nazwa statusu w sklepie; powtórz dla kilku (facets.shop_statuses).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status_type",
            "in": "query",
            "required": false,
            "description": "Comma list of new, open, closed, cancelled.",
            "x-pl-description": "Lista po przecinku: new, open, closed, cancelled.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "paid",
            "in": "query",
            "required": false,
            "description": "The shop's paid flag.",
            "x-pl-description": "Znacznik opłacenia ze sklepu.",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "total_min",
            "in": "query",
            "required": false,
            "description": "Order value at least (in the order's currency).",
            "x-pl-description": "Wartość zamówienia co najmniej (w walucie zamówienia).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "total_max",
            "in": "query",
            "required": false,
            "description": "Order value at most.",
            "x-pl-description": "Wartość zamówienia najwyżej.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "Comma list of ad source platforms: meta, google_ads, microsoft_ads, tiktok, pinterest, openai_ads, email, comparison, other, direct, unknown (unknown includes orders without one).",
            "x-pl-description": "Lista platform źródła reklamy po przecinku: meta, google_ads, microsoft_ads, tiktok, pinterest, openai_ads, email, comparison, other, direct, unknown (unknown obejmuje zamówienia bez źródła).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign",
            "in": "query",
            "required": false,
            "description": "Campaign key (a campaign id, or utm:<utm_campaign> — keys come from ad_facets); repeat for several.",
            "x-pl-description": "Klucz kampanii (identyfikator kampanii albo utm:<utm_campaign> — klucze z ad_facets); powtórz dla kilku.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ad_source",
            "in": "query",
            "required": false,
            "description": "yes = a known ad platform, no = direct or unknown.",
            "x-pl-description": "yes = znana platforma reklamy, no = wejście bezpośrednie albo nieznane.",
            "schema": {
              "type": "string",
              "enum": [
                "yes",
                "no"
              ]
            }
          },
          {
            "name": "meta_send",
            "in": "query",
            "required": false,
            "description": "Comma list of accepted, failed, waiting, none: what happened to the purchase sent to Meta.",
            "x-pl-description": "Lista po przecinku: accepted, failed, waiting, none — co stało się z zakupem wysłanym do Mety.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "product",
            "in": "query",
            "required": false,
            "description": "A line whose name contains this text, or whose code, EAN or catalogue id equals it.",
            "x-pl-description": "Pozycja, której nazwa zawiera ten tekst albo której kod, EAN lub identyfikator z katalogu jest mu równy.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "Comma list of delivery country codes.",
            "x-pl-description": "Lista kodów kraju dostawy po przecinku.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "required": false,
            "description": "Order of the list.",
            "x-pl-description": "Kolejność listy.",
            "schema": {
              "type": "string",
              "enum": [
                "placed",
                "placed_asc",
                "total",
                "total_asc",
                "items",
                "items_asc",
                "paid",
                "paid_asc"
              ],
              "default": "placed"
            }
          },
          {
            "name": "per_page",
            "in": "query",
            "required": false,
            "description": "Orders per page.",
            "x-pl-description": "Zamówień na stronę.",
            "schema": {
              "type": "integer",
              "enum": [
                10,
                25,
                50,
                100
              ],
              "default": 50
            }
          },
          {
            "name": "page",
            "in": "query",
            "required": false,
            "description": "Page, 1 = first.",
            "x-pl-description": "Strona, 1 = pierwsza.",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OrderList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "orders:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/orders/{id}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "getOrder",
        "summary": "Get an order",
        "description": "One order with its lines, buyer, ad source and the destinations its purchase went to. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pobierz zamówienie",
          "description": "Jedno zamówienie z pozycjami, kupującym, źródłem reklamy i miejscami, do których poszedł zakup. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Order"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "orders:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/templates": {
      "get": {
        "tags": [
          "Templates"
        ],
        "operationId": "listTemplates",
        "summary": "List image templates",
        "description": "Templates a feed rule or flow block can draw product images with. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Lista szablonów grafik",
          "description": "Szablony, którymi reguła feedu albo bloczek przepływu rysuje grafiki produktów. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplateList"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "templates:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/campaigns/products": {
      "get": {
        "tags": [
          "Reports"
        ],
        "operationId": "campaignProducts",
        "summary": "Products in catalogue ads",
        "description": "Per-product results of a campaign, ad group or ad from the platform's per-product report (Meta by default; Google Ads, Microsoft Ads, TikTok with `platform`), with the product's shop sales. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Produkty w reklamach katalogowych",
          "description": "Wyniki na produkt z kampanii, grupy reklam albo reklamy według raportu platformy na produkt (domyślnie Meta; Google Ads, Microsoft Ads, TikTok przez `platform`), ze sprzedażą produktu w sklepie. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD.",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "platform",
            "in": "query",
            "required": false,
            "description": "meta (default), google_ads, microsoft_ads or tiktok.",
            "x-pl-description": "meta (domyślnie), google_ads, microsoft_ads albo tiktok.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "campaign",
            "in": "query",
            "required": false,
            "description": "Only this campaign.",
            "x-pl-description": "Tylko ta kampania.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "adgroup",
            "in": "query",
            "required": false,
            "description": "Only this ad group (Google Ads, Microsoft Ads).",
            "x-pl-description": "Tylko ta grupa reklam (Google Ads, Microsoft Ads).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "ad",
            "in": "query",
            "required": false,
            "description": "Only this ad.",
            "x-pl-description": "Tylko ta reklama.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CampaignProducts"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "campaigns:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/templates/performance": {
      "get": {
        "tags": [
          "Templates"
        ],
        "operationId": "templatePerformance",
        "summary": "Template results",
        "description": "Ad results of the products of feeds that use each template. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Wyniki szablonów",
          "description": "Wyniki w reklamach produktów z feedów, które używają każdego szablonu. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "name": "from",
            "in": "query",
            "required": false,
            "description": "First day YYYY-MM-DD (default: 30 days ago).",
            "x-pl-description": "Pierwszy dzień RRRR-MM-DD (domyślnie 30 dni temu).",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "required": false,
            "description": "Last day YYYY-MM-DD.",
            "x-pl-description": "Ostatni dzień RRRR-MM-DD.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TemplatePerformance"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        },
        "x-required-scope": "templates:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    },
    "/templates/{id}": {
      "get": {
        "tags": [
          "Templates"
        ],
        "operationId": "getTemplate",
        "summary": "Get an image template",
        "description": "One template with its layers. Runs as the member who created the key: their role applies, `scope=mine` means their own work.",
        "x-pl": {
          "summary": "Pobierz szablon grafiki",
          "description": "Jeden szablon z warstwami. Działa jako osoba, która utworzyła klucz: obowiązuje jej rola, `scope=mine` oznacza jej własną pracę."
        },
        "parameters": [
          {
            "$ref": "#/components/parameters/id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "x-pl-description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Template"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        },
        "x-required-scope": "templates:read",
        "security": [
          {
            "apiKey": []
          }
        ]
      }
    }
  },
  "webhooks": {
    "contact.created": {
      "post": {
        "summary": "contact.created",
        "description": "A person was added (shop order, manual, API, automation).",
        "x-pl": {
          "summary": "contact.created",
          "description": "Dodano osobę (zamówienie w sklepie, ręcznie, przez API, automatyzacją)."
        },
        "x-example": {
          "contact_id": "abc123",
          "first_source": "Zamówienie w sklepie"
        },
        "parameters": [
          {
            "name": "X-Baskety-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`sha256=` + hex HMAC-SHA256 of `{X-Baskety-Timestamp}.{raw body}` with the webhook secret.",
            "x-pl-description": "`sha256=` + hex HMAC-SHA256 z `{X-Baskety-Timestamp}.{surowa treść}` kluczem sekretu webhooka."
          },
          {
            "name": "X-Baskety-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds of the attempt; reject values older than 5 minutes.",
            "x-pl-description": "Sekundy Unix próby; odrzucaj starsze niż 5 minut."
          },
          {
            "name": "X-Baskety-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Event type.",
            "x-pl-description": "Typ zdarzenia."
          },
          {
            "name": "X-Baskety-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery id (changes per webhook, stays across retries).",
            "x-pl-description": "Identyfikator wysyłki (inny dla każdego webhooka, ten sam przy ponowieniach)."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery; anything else is retried up to 8 times over about 2 days (1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h).",
            "x-pl-description": "Dowolny kod 2xx w ciągu 15 s potwierdza odbiór; inaczej ponawiamy do 8 razy w ciągu ok. 2 dni (1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h)."
          }
        }
      }
    },
    "delivery.failed": {
      "post": {
        "summary": "delivery.failed",
        "description": "A conversion delivery to Meta failed for good.",
        "x-pl": {
          "summary": "delivery.failed",
          "description": "Wysyłka konwersji do Meta ostatecznie się nie powiodła."
        },
        "x-example": {
          "delivery_id": "d123",
          "event_id": "e123",
          "target_id": "t123",
          "dataset_id": "123456789",
          "event_name": "Purchase",
          "mode": "live",
          "error": "Połącz konto Meta ponownie lub sprawdź token."
        },
        "parameters": [
          {
            "name": "X-Baskety-Signature",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "`sha256=` + hex HMAC-SHA256 of `{X-Baskety-Timestamp}.{raw body}` with the webhook secret.",
            "x-pl-description": "`sha256=` + hex HMAC-SHA256 z `{X-Baskety-Timestamp}.{surowa treść}` kluczem sekretu webhooka."
          },
          {
            "name": "X-Baskety-Timestamp",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Unix seconds of the attempt; reject values older than 5 minutes.",
            "x-pl-description": "Sekundy Unix próby; odrzucaj starsze niż 5 minut."
          },
          {
            "name": "X-Baskety-Event",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Event type.",
            "x-pl-description": "Typ zdarzenia."
          },
          {
            "name": "X-Baskety-Delivery",
            "in": "header",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Delivery id (changes per webhook, stays across retries).",
            "x-pl-description": "Identyfikator wysyłki (inny dla każdego webhooka, ten sam przy ponowieniach)."
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebhookEvent"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Any 2xx within 15 s acknowledges the delivery; anything else is retried up to 8 times over about 2 days (1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h).",
            "x-pl-description": "Dowolny kod 2xx w ciągu 15 s potwierdza odbiór; inaczej ponawiamy do 8 razy w ciągu ok. 2 dni (1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h)."
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "bsk_live_…",
        "x-scopes": [
          {
            "name": "contacts:read",
            "pii": true
          },
          {
            "name": "contacts:write",
            "pii": true
          },
          {
            "name": "events:read",
            "pii": false
          },
          {
            "name": "events:write",
            "pii": false
          },
          {
            "name": "tasks:read",
            "pii": true
          },
          {
            "name": "tasks:write",
            "pii": true
          },
          {
            "name": "campaigns:read",
            "pii": false
          },
          {
            "name": "creatives:read",
            "pii": false
          },
          {
            "name": "automations:read",
            "pii": false
          },
          {
            "name": "integrations:read",
            "pii": false
          },
          {
            "name": "orders:read",
            "pii": true
          },
          {
            "name": "products:read",
            "pii": false
          },
          {
            "name": "products:write",
            "pii": false
          },
          {
            "name": "feeds:read",
            "pii": false
          },
          {
            "name": "feeds:write",
            "pii": false
          },
          {
            "name": "templates:read",
            "pii": false
          },
          {
            "name": "diagnostics:read",
            "pii": false
          },
          {
            "name": "diagnostics:write",
            "pii": false
          },
          {
            "name": "jobs:read",
            "pii": false
          },
          {
            "name": "webhooks:read",
            "pii": false
          },
          {
            "name": "webhooks:write",
            "pii": false
          }
        ],
        "description": "Organisation API key created in the panel (Konfiguracja → API).",
        "x-pl-description": "Klucz API organizacji utworzony w panelu (Konfiguracja → API)."
      }
    },
    "parameters": {
      "limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Page size, 1–100 (default 25).",
        "x-pl-description": "Rozmiar strony, 1–100 (domyślnie 25).",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        }
      },
      "cursor": {
        "name": "cursor",
        "in": "query",
        "required": false,
        "description": "`next_cursor` of the previous page.",
        "x-pl-description": "`next_cursor` z poprzedniej strony.",
        "schema": {
          "type": "string"
        }
      },
      "order": {
        "name": "order",
        "in": "query",
        "required": false,
        "description": "Sort by `updated_at` (then id): `desc` newest first (default) or `asc`.",
        "x-pl-description": "Sortowanie po `updated_at` (potem id): `desc` od najnowszych (domyślnie) lub `asc`.",
        "schema": {
          "type": "string",
          "enum": [
            "asc",
            "desc"
          ],
          "default": "desc"
        }
      },
      "updated_since": {
        "name": "updated_since",
        "in": "query",
        "required": false,
        "description": "Only records changed at or after this ISO 8601 time.",
        "x-pl-description": "Tylko rekordy zmienione w tym czasie ISO 8601 lub później.",
        "schema": {
          "type": "string",
          "format": "date-time"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Unique key (1–255 visible ASCII characters). Repeating a POST with the same key and body within 24 hours returns the stored response with `Idempotent-Replayed: true`.",
        "x-pl-description": "Unikalny klucz (1–255 widocznych znaków ASCII). Powtórzenie POST z tym samym kluczem i treścią w ciągu 24 godzin zwraca zapisaną odpowiedź z `Idempotent-Replayed: true`.",
        "schema": {
          "type": "string",
          "maxLength": 255
        }
      },
      "id": {
        "name": "id",
        "in": "path",
        "required": true,
        "description": "Record id.",
        "x-pl-description": "Identyfikator rekordu.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "Invalid input (`validation_error`, `invalid_json`, `invalid_cursor`).",
        "x-pl-description": "Nieprawidłowe dane (`validation_error`, `invalid_json`, `invalid_cursor`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, unknown, revoked or expired key (`unauthorized`, `key_revoked`, `key_expired`).",
        "x-pl-description": "Brak, nieznany, unieważniony lub wygasły klucz (`unauthorized`, `key_revoked`, `key_expired`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key lacks the scope (`insufficient_scope`, `details.required_scope`).",
        "x-pl-description": "Klucz nie ma uprawnienia (`insufficient_scope`, `details.required_scope`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such record in your organisation (`not_found`).",
        "x-pl-description": "Brak takiego rekordu w Twojej organizacji (`not_found`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "Conflicts with the current state (`conflict`, `contact_exists`, `contact_merged`, `event_conflict`, `source_paused`, `idempotency_in_progress`).",
        "x-pl-description": "Konflikt z aktualnym stanem (`conflict`, `contact_exists`, `contact_merged`, `event_conflict`, `source_paused`, `idempotency_in_progress`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unprocessable": {
        "description": "Idempotency-Key reused with a different body (`idempotency_key_reused`).",
        "x-pl-description": "Idempotency-Key użyty z inną treścią (`idempotency_key_reused`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "TooLarge": {
        "description": "Body over 64 KB (`payload_too_large`).",
        "x-pl-description": "Treść ponad 64 KB (`payload_too_large`).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Over 120 requests per minute for this key (`rate_limited`); wait `Retry-After` seconds.",
        "x-pl-description": "Ponad 120 żądań na minutę tym kluczem (`rate_limited`); odczekaj `Retry-After` sekund.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            },
            "description": "Seconds to wait."
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "description": "Stable machine-readable code, e.g. `validation_error`. Never translated.",
                "x-pl-description": "Stały kod błędu do obsługi w programie, np. `validation_error`. Nigdy nie jest tłumaczony.",
                "type": "string"
              },
              "message": {
                "description": "Human-readable message in the language from `Accept-Language` (Polish by default, `en` for English).",
                "x-pl-description": "Opis dla człowieka w języku z nagłówka `Accept-Language` (domyślnie polski, `en` — angielski).",
                "type": "string"
              },
              "details": {
                "description": "Extra machine-readable context, e.g. `required_scope` or `contact_id`.",
                "x-pl-description": "Dodatkowe dane, np. `required_scope` albo `contact_id`.",
                "type": "object",
                "additionalProperties": true
              }
            },
            "required": [
              "code",
              "message"
            ]
          }
        },
        "required": [
          "error"
        ]
      },
      "Contact": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Contact id.",
            "x-pl-description": "Identyfikator osoby.",
            "type": "string"
          },
          "name": {
            "description": "Full name.",
            "x-pl-description": "Imię i nazwisko.",
            "type": "string"
          },
          "phone": {
            "description": "Phone in E.164 form, empty when unknown.",
            "x-pl-description": "Telefon w formacie E.164, pusty gdy nieznany.",
            "type": "string"
          },
          "email": {
            "description": "E-mail, empty when unknown.",
            "x-pl-description": "E-mail, pusty gdy nieznany.",
            "type": "string"
          },
          "tags": {
            "description": "Tags.",
            "x-pl-description": "Tagi.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sms_optout": {
            "description": "True when SMS to this person are blocked.",
            "x-pl-description": "Prawda, gdy SMS-y do tej osoby są zablokowane.",
            "type": "boolean"
          },
          "first_source": {
            "description": "Where the person first came from (\"Zamówienie w sklepie\", \"Ręcznie\", API…).",
            "x-pl-description": "Skąd osoba przyszła po raz pierwszy („Zamówienie w sklepie”, „Ręcznie”, API…).",
            "type": "string"
          },
          "status_id": {
            "description": "Internal status id (GET /contact-statuses), null when none. Never sent to Meta.",
            "x-pl-description": "Identyfikator statusu wewnętrznego (GET /contact-statuses), null gdy brak. Nigdy nie trafia do Mety.",
            "type": [
              "string",
              "null"
            ]
          },
          "owner_id": {
            "description": "User id of the person's owner (opiekun).",
            "x-pl-description": "Identyfikator użytkownika — opiekuna osoby.",
            "type": [
              "string",
              "null"
            ]
          },
          "last_activity_at": {
            "description": "Last activity time.",
            "x-pl-description": "Czas ostatniej aktywności.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change; use with `updated_since`.",
            "x-pl-description": "Ostatnia zmiana; używaj z `updated_since`.",
            "type": "string",
            "format": "date-time"
          },
          "orders": {
            "type": "object",
            "properties": {
              "count": {
                "description": "Bought, not cancelled shop orders.",
                "x-pl-description": "Kupione, nieanulowane zamówienia ze sklepu.",
                "type": "integer"
              },
              "value": {
                "description": "Their value in `currency`.",
                "x-pl-description": "Ich wartość w `currency`.",
                "type": "number"
              },
              "currency": {
                "description": "The currency most of the orders use.",
                "x-pl-description": "Waluta większości zamówień.",
                "type": "string"
              },
              "first_at": {
                "description": "First order time.",
                "x-pl-description": "Czas pierwszego zamówienia.",
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              },
              "last_at": {
                "description": "Last order time.",
                "x-pl-description": "Czas ostatniego zamówienia.",
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            },
            "description": "What the person bought in the shop.",
            "x-pl-description": "Co osoba kupiła w sklepie."
          }
        }
      },
      "ContactList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Contact"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "ContactCreate": {
        "type": "object",
        "properties": {
          "name": {
            "description": "Full name (up to 200 characters).",
            "x-pl-description": "Imię i nazwisko (do 200 znaków).",
            "type": "string",
            "maxLength": 200
          },
          "phone": {
            "description": "Phone with a country code, e.g. +48 600 857 482, or 9 digits (Poland).",
            "x-pl-description": "Telefon z numerem kierunkowym, np. +48 600 857 482, albo 9 cyfr.",
            "type": "string"
          },
          "email": {
            "description": "E-mail address.",
            "x-pl-description": "Adres e-mail.",
            "type": "string",
            "maxLength": 254
          },
          "tags": {
            "description": "Tags.",
            "x-pl-description": "Tagi.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": "A phone or an e-mail is required. A person with the same phone or e-mail is not duplicated: the answer is 409 `contact_exists` with `details.contact_id`.",
        "x-pl-description": "Wymagany jest telefon lub e-mail. Osoba z tym samym telefonem lub e-mailem nie jest dublowana: odpowiedź to 409 `contact_exists` z `details.contact_id`.",
        "additionalProperties": false
      },
      "ContactUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "description": "Full name.",
            "x-pl-description": "Imię i nazwisko.",
            "type": "string"
          },
          "phone": {
            "description": "Phone; an empty string removes it (a phone or an e-mail must remain).",
            "x-pl-description": "Telefon; pusty tekst usuwa go (musi zostać telefon lub e-mail).",
            "type": "string"
          },
          "email": {
            "description": "E-mail; an empty string removes it.",
            "x-pl-description": "E-mail; pusty tekst usuwa go.",
            "type": "string"
          },
          "tags": {
            "description": "Replaces all tags.",
            "x-pl-description": "Zastępuje wszystkie tagi.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": "Only the fields you send change. Each change is written to the person's history.",
        "x-pl-description": "Zmieniają się tylko wysłane pola. Każda zmiana trafia do historii osoby.",
        "additionalProperties": false
      },
      "NoteCreate": {
        "type": "object",
        "properties": {
          "kind": {
            "description": "Entry kind.",
            "x-pl-description": "Rodzaj wpisu.",
            "type": "string",
            "enum": [
              "note",
              "call",
              "meeting"
            ],
            "default": "note"
          },
          "text": {
            "description": "Text, 1–5000 characters.",
            "x-pl-description": "Treść, 1–5000 znaków.",
            "type": "string",
            "maxLength": 5000
          },
          "time": {
            "description": "When it happened (default: now); not in the future.",
            "x-pl-description": "Kiedy to było (domyślnie teraz); nie w przyszłości.",
            "type": "string",
            "format": "date-time"
          }
        },
        "required": [
          "text"
        ],
        "additionalProperties": false
      },
      "Note": {
        "type": "object",
        "properties": {
          "id": {
            "description": "History entry id.",
            "x-pl-description": "Identyfikator wpisu historii.",
            "type": "string"
          },
          "contact_id": {
            "description": "Contact id.",
            "x-pl-description": "Identyfikator osoby.",
            "type": "string"
          },
          "kind": {
            "description": "Entry kind.",
            "x-pl-description": "Rodzaj wpisu.",
            "type": "string"
          },
          "text": {
            "description": "Text.",
            "x-pl-description": "Treść.",
            "type": "string"
          },
          "time": {
            "description": "Entry time.",
            "x-pl-description": "Czas wpisu.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "TagsChange": {
        "type": "object",
        "properties": {
          "add": {
            "description": "Tags to add.",
            "x-pl-description": "Tagi do dodania.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "remove": {
            "description": "Tags to remove.",
            "x-pl-description": "Tagi do usunięcia.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "additionalProperties": false
      },
      "OptoutChange": {
        "type": "object",
        "properties": {
          "sms_optout": {
            "description": "True blocks SMS to the person's phone (for every person sharing it), false allows them again.",
            "x-pl-description": "true blokuje SMS-y na telefon osoby (dla wszystkich osób z tym numerem), false ponownie je dopuszcza.",
            "type": "boolean"
          }
        },
        "required": [
          "sms_optout"
        ],
        "additionalProperties": false
      },
      "EventCreate": {
        "type": "object",
        "properties": {
          "source": {
            "description": "Id of a Google Sheets or shop source of your organisation (Połączenia → source details).",
            "x-pl-description": "Identyfikator źródła Arkusz Google lub sklepu Twojej organizacji (Połączenia → szczegóły źródła).",
            "type": "string"
          },
          "external_id": {
            "description": "Your id of the record (order number…), max 128 characters.",
            "x-pl-description": "Twój identyfikator rekordu (numer zamówienia…), do 128 znaków.",
            "type": "string",
            "maxLength": 128
          },
          "status": {
            "description": "Your status mapped to a Meta event by the source's flow, e.g. QUALIFIED or purchase.",
            "x-pl-description": "Twój status zamapowany na zdarzenie Meta przez przepływ źródła, np. QUALIFIED albo purchase.",
            "type": "string",
            "maxLength": 80
          },
          "consent": {
            "description": "Must be true: you confirm a legal basis for sending the data.",
            "x-pl-description": "Musi być true: potwierdzasz podstawę prawną przesłania danych.",
            "type": "boolean"
          },
          "event_time": {
            "description": "Unix seconds or ISO 8601; at most 7 days old.",
            "x-pl-description": "Sekundy Unix lub ISO 8601; najwyżej 7 dni wstecz.",
            "oneOf": [
              {
                "type": "integer"
              },
              {
                "type": "string",
                "format": "date-time"
              }
            ]
          },
          "event_id": {
            "description": "Meta deduplication id; generated from source + external_id + status when omitted.",
            "x-pl-description": "Identyfikator deduplikacji Meta; bez niego powstaje z source + external_id + status.",
            "type": "string"
          },
          "email": {
            "description": "Customer e-mail (hashed with SHA-256 before storage).",
            "x-pl-description": "E-mail klienta (haszowany SHA-256 przed zapisem).",
            "type": "string"
          },
          "phone": {
            "description": "Customer phone in E.164 (hashed).",
            "x-pl-description": "Telefon klienta w E.164 (haszowany).",
            "type": "string"
          },
          "lead_id": {
            "description": "Meta lead id of the customer, when you have one; sent to Meta as customer information.",
            "x-pl-description": "Identyfikator leada Meta klienta, jeśli go masz; trafia do Mety jako dane klienta.",
            "type": "string"
          },
          "user_id": {
            "description": "Your customer id (hashed as external_id).",
            "x-pl-description": "Twój identyfikator klienta (haszowany jako external_id).",
            "type": "string"
          },
          "fbp": {
            "description": "_fbp cookie.",
            "x-pl-description": "Ciasteczko _fbp.",
            "type": "string"
          },
          "fbc": {
            "description": "_fbc cookie.",
            "x-pl-description": "Ciasteczko _fbc.",
            "type": "string"
          },
          "event_source_url": {
            "description": "Page URL of the conversion.",
            "x-pl-description": "Adres strony konwersji.",
            "type": "string"
          },
          "tracking_id": {
            "description": "Collector tracking id (shop sources).",
            "x-pl-description": "Identyfikator śledzenia kolektora (źródła sklepów).",
            "type": "string"
          },
          "client_ip_address": {
            "description": "Customer IP.",
            "x-pl-description": "IP klienta.",
            "type": "string"
          },
          "client_user_agent": {
            "description": "Customer user agent.",
            "x-pl-description": "User agent klienta.",
            "type": "string"
          },
          "value": {
            "description": "Conversion value (required for Purchase).",
            "x-pl-description": "Wartość konwersji (wymagana dla Purchase).",
            "type": "number"
          },
          "currency": {
            "description": "ISO 4217 currency (required with value).",
            "x-pl-description": "Waluta ISO 4217 (wymagana z wartością).",
            "type": "string"
          },
          "content_ids": {
            "description": "Product ids.",
            "x-pl-description": "Identyfikatory produktów.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "source",
          "external_id",
          "status",
          "consent"
        ],
        "description": "The same rules as source ingest: dedupe on source + external_id + status, an event with the same identity and different data is refused (409 `event_conflict`).",
        "x-pl-description": "Te same zasady co przyjmowanie przez źródło: deduplikacja po source + external_id + status, zdarzenie o tej samej tożsamości z innymi danymi jest odrzucane (409 `event_conflict`).",
        "additionalProperties": false
      },
      "EventAccepted": {
        "type": "object",
        "properties": {
          "event_id": {
            "description": "Basketly event id.",
            "x-pl-description": "Identyfikator zdarzenia w Basketly.",
            "type": "string"
          },
          "deliveries_created": {
            "description": "New deliveries queued for Meta datasets.",
            "x-pl-description": "Nowe wysyłki dodane do kolejki dla datasetów Meta.",
            "type": "integer"
          },
          "duplicates": {
            "description": "Deliveries skipped as duplicates.",
            "x-pl-description": "Wysyłki pominięte jako duplikaty.",
            "type": "integer"
          },
          "sending_enabled": {
            "description": "False when the server does not send to Meta (queued only).",
            "x-pl-description": "false, gdy serwer nie wysyła do Meta (tylko kolejka).",
            "type": "boolean"
          }
        }
      },
      "Delivery": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Delivery id.",
            "x-pl-description": "Identyfikator wysyłki.",
            "type": "string"
          },
          "event_id": {
            "description": "Basketly event id.",
            "x-pl-description": "Identyfikator zdarzenia w Basketly.",
            "type": "string"
          },
          "target_id": {
            "description": "Meta receiver (dataset connection) id.",
            "x-pl-description": "Identyfikator odbiorcy Meta (połączenia z datasetem).",
            "type": "string"
          },
          "dataset_id": {
            "description": "Meta dataset (pixel) id.",
            "x-pl-description": "Identyfikator datasetu (piksela) Meta.",
            "type": "string"
          },
          "event_name": {
            "description": "Meta event name, e.g. Purchase, AddToCart.",
            "x-pl-description": "Nazwa zdarzenia Meta, np. Purchase, AddToCart.",
            "type": "string"
          },
          "meta_event_id": {
            "description": "event_id sent to Meta.",
            "x-pl-description": "event_id wysłane do Meta.",
            "type": "string"
          },
          "mode": {
            "description": "`test` or `live`.",
            "x-pl-description": "`test` albo `live`.",
            "type": "string"
          },
          "status": {
            "description": "Delivery status.",
            "x-pl-description": "Status wysyłki.",
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "retry",
              "accepted",
              "failed",
              "cancelled"
            ]
          },
          "attempts": {
            "description": "Attempts so far.",
            "x-pl-description": "Dotychczasowe próby.",
            "type": "integer"
          },
          "last_error": {
            "description": "Last error, empty when none.",
            "x-pl-description": "Ostatni błąd, pusty gdy brak.",
            "type": "string"
          },
          "accepted_at": {
            "description": "When Meta accepted it (receipt, not proof of attribution).",
            "x-pl-description": "Kiedy Meta przyjęła wysyłkę (odbiór, nie dowód atrybucji).",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "next_attempt_at": {
            "description": "Next attempt.",
            "x-pl-description": "Następna próba.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change.",
            "x-pl-description": "Ostatnia zmiana.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "DeliveryList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Delivery"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "Event": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Event id.",
            "x-pl-description": "Identyfikator zdarzenia.",
            "type": "string"
          },
          "source_id": {
            "description": "Source id.",
            "x-pl-description": "Identyfikator źródła.",
            "type": "string"
          },
          "external_id": {
            "description": "Your record id.",
            "x-pl-description": "Twój identyfikator rekordu.",
            "type": "string"
          },
          "status": {
            "description": "Your status.",
            "x-pl-description": "Twój status.",
            "type": "string"
          },
          "meta_event_id": {
            "description": "Meta deduplication id.",
            "x-pl-description": "Identyfikator deduplikacji Meta.",
            "type": "string"
          },
          "event_time": {
            "description": "Event time.",
            "x-pl-description": "Czas zdarzenia.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "value": {
            "description": "Value.",
            "x-pl-description": "Wartość.",
            "type": [
              "number",
              "null"
            ]
          },
          "currency": {
            "description": "Currency.",
            "x-pl-description": "Waluta.",
            "type": "string"
          },
          "deliveries": {
            "description": "Deliveries of this event.",
            "x-pl-description": "Wysyłki tego zdarzenia.",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Delivery"
            }
          },
          "created_at": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change.",
            "x-pl-description": "Ostatnia zmiana.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "EventList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Event"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "CampaignReport": {
        "type": "object",
        "properties": {
          "from": {
            "description": "First day (organisation time zone).",
            "x-pl-description": "Pierwszy dzień (strefa czasowa organizacji).",
            "type": "string"
          },
          "to": {
            "description": "Last day.",
            "x-pl-description": "Ostatni dzień.",
            "type": "string"
          },
          "level": {
            "description": "Row level.",
            "x-pl-description": "Poziom wierszy.",
            "type": "string",
            "enum": [
              "campaign",
              "adset",
              "ad"
            ]
          },
          "totals": {
            "description": "Totals per currency: `current` and the `previous` period of the same length. Without a campaign/adset filter they also carry the shop's bought orders of the period (`shop_orders`, `shop_revenue`) and `mer` = shop revenue / spend. Totals and rows also carry `baskety_orders`, `baskety_revenue`, `baskety_currency`: bought orders whose ad source (Basketly's last-click reading of the buyer's visits) is a Meta campaign / ad set / ad of the row — a different count from Meta's purchases, never added to them.",
            "x-pl-description": "Sumy w każdej walucie: `current` i poprzedni okres tej samej długości (`previous`). Bez filtra kampanii/zestawu zawierają też opłacone zamówienia sklepu z okresu (`shop_orders`, `shop_revenue`) i `mer` = przychód sklepu / wydatki. Sumy i wiersze mają też `baskety_orders`, `baskety_revenue`, `baskety_currency`: opłacone zamówienia, których źródłem reklamy (odczytanie Basketly z wizyt kupującego) jest kampania / zestaw / reklama Mety z wiersza — inna liczba niż zakupy Mety, nigdy do nich nie dodawana.",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "rows": {
            "description": "One row per campaign / ad set / ad with `status` (Meta's effective status), `optimization` (what its ad sets optimize for: `label` in Polish — Meta's standard events named in Polish, e.g. „Zdarzenie: Zakup (zbiór …)” — `event` and, for an event goal, `event_name` = Meta's technical name such as Purchase, `short` = the goal in words without the dataset for a badge, e.g. „Zakup”) and `metrics`: spend, purchases, purchase_value, cost_per_purchase, roas (purchases and their value as Meta reports them); delivery summed over the period's days — impressions, clicks (all clicks), cpm (spend / impressions × 1000), link_clicks, ctr (link clicks / impressions, a fraction), cpc (spend / link click; link figures count only days read with link clicks, null before), video plays_3s, thruplays, p25, p50, p75, p100, hook_rate (3 s plays / impressions) and hold_rate (ThruPlays / 3 s plays; null for images); costs and ratios are null when the divisor is 0. Reach and frequency are not offered (daily reach cannot be added up). Plus `baskety_orders` / `baskety_revenue` from the orders' ad source. Totals carry the same delivery fields. Każdy wiersz podaje też konto reklamowe Mety: `ad_account_id` i `ad_account_name` (puste, dopóki nie odczytane).",
            "x-pl-description": "Wiersz na kampanię / zestaw / reklamę ze `status` (stan w Mecie), `optimization` (na co optymalizują jego zestawy: `label` po polsku — standardowe zdarzenia Mety po polsku, np. „Zdarzenie: Zakup (zbiór …)” — `event` i przy celu na zdarzenie `event_name` = techniczna nazwa w Mecie, np. Purchase, `short` = cel słowami bez zbioru na plakietkę, np. „Zakup”) i `metrics`: spend, purchases, purchase_value, cost_per_purchase, roas (zakupy i ich wartość według raportu Mety); dostarczanie zsumowane z dni okresu — impressions, clicks (wszystkie kliknięcia), cpm (wydatki / wyświetlenia × 1000), link_clicks, ctr (kliknięcia linku / wyświetlenia, ułamek), cpc (wydatki / kliknięcie linku; liczby linków tylko z dni odczytanych z kliknięciami linku, wcześniej null), wideo plays_3s, thruplays, p25, p50, p75, p100, hook_rate (odtworzenia 3 s / wyświetlenia) i hold_rate (ThruPlay / odtworzenia 3 s; null dla obrazów); koszty i wskaźniki są null przy zerowym dzielniku. Zasięgu i częstotliwości nie ma (dziennego zasięgu nie da się zsumować). Do tego `baskety_orders` / `baskety_revenue` ze źródła zamówień. Sumy mają te same pola dostarczania.",
            "type": "array Each row also names its Meta ad account: `ad_account_id` and `ad_account_name` (empty until read).",
            "items": {
              "type": "object"
            }
          },
          "syncs": {
            "description": "Spend sync state per ad account: `ad_account_id` (act_…), `ad_account_name` (the account's name in Meta; empty until the next spend read stores it), `currency`, `last_success`, `last_error` and `job` while it waits or is read.",
            "x-pl-description": "Stan synchronizacji wydatków na konto reklamowe: `ad_account_id` (act_…), `ad_account_name` (nazwa konta w Mecie; pusta, dopóki następny odczyt wydatków jej nie zapisze), `currency`, `last_success`, `last_error` oraz `job`, gdy konto czeka albo jest czytane.",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "comparison": {
            "description": "How the totals compare with the previous period: {mode whole|same_hour, until, previous_until, spend_without_today, spend_to, previous_spend_to}. A period that ends today compares Meta's figures and MER over whole days (today left out of both periods) and the shop's and Basketly's orders up to the same hour; each total's `compare` holds the current figures to set against `previous` (`current` still counts today).",
            "x-pl-description": "Jak sumy porównują się z poprzednim okresem: {mode whole|same_hour, until, previous_until, spend_without_today, spend_to, previous_spend_to}. Okres kończący się dziś porównuje liczby Mety i MER po pełnych dniach (bez dzisiejszego w obu okresach), a zamówienia sklepu i Basketly do tej samej godziny; `compare` każdej sumy to bieżące liczby do zestawienia z `previous` (`current` nadal obejmuje dzisiejszy dzień).",
            "type": "object"
          },
          "shops": {
            "description": "Kinds of the connected shops (shoper, idosell, baselinker…) whose orders give the shop's numbers.",
            "x-pl-description": "Rodzaje podłączonych sklepów (shoper, idosell, baselinker…), z których zamówień pochodzą liczby sklepu.",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "description": "The same numbers as the Kampanie page.",
        "x-pl-description": "Te same liczby co na stronie Kampanie."
      },
      "CreativeReport": {
        "type": "object",
        "properties": {
          "from": {
            "description": "First day.",
            "x-pl-description": "Pierwszy dzień.",
            "type": "string"
          },
          "to": {
            "description": "Last day.",
            "x-pl-description": "Ostatni dzień.",
            "type": "string"
          },
          "weeks": {
            "description": "Week ranges used for momentum.",
            "x-pl-description": "Zakresy tygodni użyte do trendu.",
            "type": "array",
            "items": {
              "type": "array"
            }
          },
          "rows": {
            "description": "One row per creative group (same video, image or creative) with metrics, weekly trend, fatigue verdict and tags. `baskety_orders` / `baskety_revenue` (in `baskety_currency`): bought shop orders of the period whose ad source (Basketly's last-click reading of the buyer's visits) is one of the creative's ads — a different count from Meta's purchases, never added to them. `ad_accounts` to identyfikatory kont reklamowych Mety grupy, a `ad_account_names` ich nazwy w tej samej kolejności (puste, dopóki nie odczytane).",
            "x-pl-description": "Wiersz na grupę kreacji (ten sam film, obraz lub kreacja) z metrykami, trendem tygodniowym, oceną zmęczenia i tagami. `baskety_orders` / `baskety_revenue` (w `baskety_currency`): opłacone zamówienia sklepu z okresu, których źródłem reklamowym (odczyt Basketly z ostatniego kliknięcia w wizytach kupującego) jest jedna z reklam kreacji — inna liczba niż zakupy Mety, nigdy do nich nie dodawana.",
            "type": "array `ad_accounts` lists the Meta ad account ids of the group and `ad_account_names` their names in the same order (empty until read).",
            "items": {
              "type": "object"
            }
          },
          "totals": {
            "description": "Totals per currency.",
            "x-pl-description": "Sumy w każdej walucie.",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "compare_totals": {
            "description": "The current totals to set against `previous_totals`: when the period ends today, the same creatives over whole days without today (Meta reports per day); otherwise equal to `totals`. Empty for a period of today only (nothing to compare).",
            "x-pl-description": "Bieżące sumy do zestawienia z `previous_totals`: gdy okres kończy się dziś, te same kreacje po pełnych dniach bez dzisiejszego (Meta podaje dane za dzień); w przeciwnym razie równe `totals`. Puste dla okresu tylko z dzisiejszego dnia (nie ma czego porównać).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "comparison": {
            "description": "How the totals compare with the previous period: {mode whole|same_hour, until, previous_until, spend_without_today, spend_to, previous_spend_to}; previous_totals then leave out the matching last day.",
            "x-pl-description": "Jak sumy porównują się z poprzednim okresem: {mode whole|same_hour, until, previous_until, spend_without_today, spend_to, previous_spend_to}; previous_totals pomijają wtedy odpowiadający dzień na końcu.",
            "type": "object"
          },
          "previous_totals": {
            "description": "Totals per currency of the same filtered creatives over the period of the same length just before `from` (the comparison under the Kreacje summary; when the period ends today, without its last day — see `comparison`).",
            "x-pl-description": "Sumy w każdej walucie tych samych (przefiltrowanych) kreacji z okresu tej samej długości tuż przed `from` (porównanie pod podsumowaniem Kreacji; gdy okres kończy się dziś, bez jego ostatniego dnia — zob. `comparison`).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "syncs": {
            "description": "Spend sync state per ad account: `ad_account_id` (act_…), `ad_account_name` (the account's name in Meta; empty until the next spend read stores it), `currency`, `last_success`, `last_error` and `job` while it waits or is read.",
            "x-pl-description": "Stan synchronizacji wydatków na konto reklamowe: `ad_account_id` (act_…), `ad_account_name` (nazwa konta w Mecie; pusta, dopóki następny odczyt wydatków jej nie zapisze), `currency`, `last_success`, `last_error` oraz `job`, gdy konto czeka albo jest czytane.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "description": "The same numbers as the Kreacje page.",
        "x-pl-description": "Te same liczby co na stronie Kreacje."
      },
      "Job": {
        "type": "object",
        "properties": {
          "number": {
            "description": "Job number within the organisation.",
            "x-pl-description": "Numer zadania w organizacji.",
            "type": "integer"
          },
          "kind": {
            "description": "Job kind, e.g. ad_spend, shoper_orders, sheets_sync.",
            "x-pl-description": "Rodzaj zadania, np. ad_spend, shoper_orders, sheets_sync.",
            "type": "string"
          },
          "label": {
            "description": "Description.",
            "x-pl-description": "Opis.",
            "type": "string"
          },
          "status": {
            "description": "Status.",
            "x-pl-description": "Status.",
            "type": "string",
            "enum": [
              "queued",
              "running",
              "done",
              "failed",
              "cancelled"
            ]
          },
          "priority": {
            "description": "`user` or `background`.",
            "x-pl-description": "`user` albo `background`.",
            "type": "string"
          },
          "trigger": {
            "description": "What started it.",
            "x-pl-description": "Co je uruchomiło.",
            "type": "string"
          },
          "progress": {
            "description": "`done` count and `text`.",
            "x-pl-description": "Licznik `done` i opis `text`.",
            "type": "object"
          },
          "attempts": {
            "description": "Attempts.",
            "x-pl-description": "Próby.",
            "type": "integer"
          },
          "error": {
            "description": "Error text of a failed job.",
            "x-pl-description": "Błąd nieudanego zadania.",
            "type": "string"
          },
          "summary": {
            "description": "Result summary.",
            "x-pl-description": "Podsumowanie wyniku.",
            "type": "string"
          },
          "run_after": {
            "description": "Not before.",
            "x-pl-description": "Nie wcześniej niż.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "started_at": {
            "description": "Start.",
            "x-pl-description": "Start.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "finished_at": {
            "description": "End.",
            "x-pl-description": "Koniec.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change.",
            "x-pl-description": "Ostatnia zmiana.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "JobList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Job"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "Webhook": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Webhook id.",
            "x-pl-description": "Identyfikator webhooka.",
            "type": "string"
          },
          "url": {
            "description": "HTTPS endpoint that receives POSTs.",
            "x-pl-description": "Adres HTTPS, który odbiera POST-y.",
            "type": "string"
          },
          "description": {
            "description": "Your note.",
            "x-pl-description": "Twój opis.",
            "type": "string"
          },
          "events": {
            "description": "Subscribed events.",
            "x-pl-description": "Subskrybowane zdarzenia.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "delivery.failed"
              ]
            }
          },
          "active": {
            "description": "False pauses deliveries.",
            "x-pl-description": "false wstrzymuje wysyłki.",
            "type": "boolean"
          },
          "last_status": {
            "description": "HTTP status of the last attempt (0 = no answer).",
            "x-pl-description": "Status HTTP ostatniej próby (0 = brak odpowiedzi).",
            "type": "integer"
          },
          "last_error": {
            "description": "Last error.",
            "x-pl-description": "Ostatni błąd.",
            "type": "string"
          },
          "last_delivery_at": {
            "description": "Last attempt.",
            "x-pl-description": "Ostatnia próba.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "consecutive_failures": {
            "description": "Failed attempts in a row.",
            "x-pl-description": "Nieudane próby z rzędu.",
            "type": "integer"
          },
          "created_at": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change.",
            "x-pl-description": "Ostatnia zmiana.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookCreated": {
        "allOf": [
          {
            "$ref": "#/components/schemas/Webhook"
          },
          {
            "type": "object",
            "properties": {
              "secret": {
                "description": "Signing secret (`whsec_…`). Shown only in this response — store it.",
                "x-pl-description": "Sekret podpisu (`whsec_…`). Widoczny tylko w tej odpowiedzi — zapisz go.",
                "type": "string"
              }
            },
            "required": [
              "secret"
            ]
          }
        ]
      },
      "WebhookList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Webhook"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "WebhookCreate": {
        "type": "object",
        "properties": {
          "url": {
            "description": "HTTPS URL (no credentials, no private or local addresses).",
            "x-pl-description": "Adres HTTPS (bez loginu i hasła, bez adresów prywatnych i lokalnych).",
            "type": "string",
            "maxLength": 2000
          },
          "events": {
            "description": "Events to receive.",
            "x-pl-description": "Zdarzenia do odbierania.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "delivery.failed"
              ]
            }
          },
          "description": {
            "description": "Your note.",
            "x-pl-description": "Twój opis.",
            "type": "string",
            "maxLength": 200
          }
        },
        "required": [
          "url",
          "events"
        ],
        "additionalProperties": false
      },
      "WebhookUpdate": {
        "type": "object",
        "properties": {
          "url": {
            "description": "New URL.",
            "x-pl-description": "Nowy adres.",
            "type": "string"
          },
          "events": {
            "description": "New event list.",
            "x-pl-description": "Nowa lista zdarzeń.",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "contact.created",
                "delivery.failed"
              ]
            }
          },
          "description": {
            "description": "Your note.",
            "x-pl-description": "Twój opis.",
            "type": "string"
          },
          "active": {
            "description": "Pause or resume.",
            "x-pl-description": "Wstrzymaj lub wznów.",
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "WebhookDelivery": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Delivery id (header X-Baskety-Delivery).",
            "x-pl-description": "Identyfikator wysyłki (nagłówek X-Baskety-Delivery).",
            "type": "string"
          },
          "webhook_id": {
            "description": "Webhook id.",
            "x-pl-description": "Identyfikator webhooka.",
            "type": "string"
          },
          "event": {
            "description": "Event type.",
            "x-pl-description": "Typ zdarzenia.",
            "type": "string"
          },
          "event_id": {
            "description": "Event id (`evt_…`, the same for every webhook of one event).",
            "x-pl-description": "Identyfikator zdarzenia (`evt_…`, ten sam dla wszystkich webhooków jednego zdarzenia).",
            "type": "string"
          },
          "status": {
            "description": "Status.",
            "x-pl-description": "Status.",
            "type": "string",
            "enum": [
              "pending",
              "sending",
              "retry",
              "delivered",
              "failed",
              "cancelled"
            ]
          },
          "attempts": {
            "description": "Attempts.",
            "x-pl-description": "Próby.",
            "type": "integer"
          },
          "response_status": {
            "description": "HTTP status of the last attempt.",
            "x-pl-description": "Status HTTP ostatniej próby.",
            "type": "integer"
          },
          "last_error": {
            "description": "Last error.",
            "x-pl-description": "Ostatni błąd.",
            "type": "string"
          },
          "next_attempt_at": {
            "description": "Next attempt.",
            "x-pl-description": "Następna próba.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "delivered_at": {
            "description": "Delivered at.",
            "x-pl-description": "Dostarczono.",
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "description": "Creation time.",
            "x-pl-description": "Czas utworzenia.",
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "description": "Last change.",
            "x-pl-description": "Ostatnia zmiana.",
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "WebhookDeliveryList": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/WebhookDelivery"
            }
          },
          "next_cursor": {
            "description": "Pass as `cursor` to get the next page; null on the last page.",
            "x-pl-description": "Przekaż jako `cursor`, by pobrać następną stronę; null na ostatniej stronie.",
            "type": [
              "string",
              "null"
            ]
          },
          "has_more": {
            "description": "True when another page exists.",
            "x-pl-description": "Prawda, gdy istnieje kolejna strona.",
            "type": "boolean"
          }
        },
        "required": [
          "data",
          "next_cursor",
          "has_more"
        ]
      },
      "WebhookEvent": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Event id `evt_…`; use it to ignore repeats (delivery is at least once).",
            "x-pl-description": "Identyfikator `evt_…`; użyj go, by pominąć powtórzenia (dostarczanie co najmniej raz).",
            "type": "string"
          },
          "type": {
            "description": "Event type.",
            "x-pl-description": "Typ zdarzenia.",
            "type": "string",
            "enum": [
              "contact.created",
              "delivery.failed",
              "ping"
            ]
          },
          "created_at": {
            "description": "When it happened.",
            "x-pl-description": "Kiedy to się stało.",
            "type": "string",
            "format": "date-time"
          },
          "organization_id": {
            "description": "Organisation id.",
            "x-pl-description": "Identyfikator organizacji.",
            "type": "string"
          },
          "data": {
            "description": "Ids and states only — read names, phones and e-mails with GET using your key.",
            "x-pl-description": "Tylko identyfikatory i stany — imiona, telefony i e-maile pobierz przez GET swoim kluczem.",
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "id",
          "type",
          "created_at",
          "organization_id",
          "data"
        ]
      },
      "WebhookTest": {
        "type": "object",
        "properties": {
          "delivery_id": {
            "description": "Queued delivery of a `ping` event.",
            "x-pl-description": "Wysyłka zdarzenia `ping` dodana do kolejki.",
            "type": "string"
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "organization": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              }
            }
          },
          "key": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "prefix": {
                "type": "string"
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "rate_limit": {
            "type": "object",
            "properties": {
              "per_minute": {
                "type": "integer"
              }
            }
          }
        }
      },
      "TaskList": {
        "type": "object",
        "properties": {
          "data": {
            "description": "Tasks by due time.",
            "x-pl-description": "Zadania wg terminu.",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "counts": {
            "description": "Counts per section (overdue, today, later, none).",
            "x-pl-description": "Liczby na sekcję (po terminie, dziś, później, bez terminu).",
            "type": "object"
          },
          "truncated": {
            "description": "More than 500 open tasks.",
            "x-pl-description": "Ponad 500 otwartych zadań.",
            "type": "boolean"
          }
        },
        "description": "Open tasks (the panel's Moje zadania), up to 500.",
        "x-pl-description": "Otwarte zadania (Moje zadania w panelu), do 500."
      },
      "TaskCreate": {
        "type": "object",
        "properties": {
          "title": {
            "description": "Task title.",
            "x-pl-description": "Tytuł zadania.",
            "type": "string",
            "maxLength": 200
          },
          "note": {
            "description": "Note.",
            "x-pl-description": "Notatka.",
            "type": "string"
          },
          "due_date": {
            "description": "Due day YYYY-MM-DD (organisation's zone); without it no due date.",
            "x-pl-description": "Dzień terminu RRRR-MM-DD (strefa organizacji); bez niego bez terminu.",
            "type": "string"
          },
          "due_time": {
            "description": "Due time HH:MM; without it the end of the day.",
            "x-pl-description": "Godzina HH:MM; bez niej koniec dnia.",
            "type": "string"
          },
          "assignee": {
            "description": "Member id (default: the person's owner or the key's member).",
            "x-pl-description": "Identyfikator członka (domyślnie opiekun osoby albo osoba klucza).",
            "type": "string"
          }
        },
        "required": [
          "title"
        ],
        "additionalProperties": false
      },
      "TaskDone": {
        "type": "object",
        "properties": {
          "entry": {
            "type": "object",
            "properties": {
              "kind": {
                "description": "Entry kind.",
                "x-pl-description": "Rodzaj wpisu.",
                "type": "string",
                "enum": [
                  "note",
                  "call",
                  "meeting"
                ]
              },
              "text": {
                "description": "Text.",
                "x-pl-description": "Treść.",
                "type": "string"
              }
            },
            "required": [
              "kind",
              "text"
            ],
            "description": "Optional history entry written with the task (e.g. the call that closed it).",
            "x-pl-description": "Opcjonalny wpis w historii zapisany razem z zadaniem (np. rozmowa, która je zamknęła).",
            "additionalProperties": false
          }
        },
        "additionalProperties": false
      },
      "TaskPostpone": {
        "type": "object",
        "properties": {
          "days": {
            "description": "Move by 1–30 days.",
            "x-pl-description": "Przesuń o 1–30 dni.",
            "type": "integer",
            "minimum": 1,
            "maximum": 30
          },
          "due_date": {
            "description": "Or a new day YYYY-MM-DD.",
            "x-pl-description": "Albo nowy dzień RRRR-MM-DD.",
            "type": "string"
          },
          "due_time": {
            "description": "With due_date: time HH:MM.",
            "x-pl-description": "Z due_date: godzina HH:MM.",
            "type": "string"
          }
        },
        "description": "Exactly one of days or due_date.",
        "x-pl-description": "Dokładnie jedno z: days albo due_date.",
        "additionalProperties": false
      },
      "Created": {
        "type": "object",
        "properties": {
          "id": {
            "description": "New record id.",
            "x-pl-description": "Identyfikator nowego rekordu.",
            "type": "string"
          }
        },
        "required": [
          "id"
        ],
        "additionalProperties": false
      },
      "ContactSearch": {
        "type": "object",
        "properties": {
          "data": {
            "description": "People: id, name, status, owner, tags, last activity, added (created), orders (count, value, first and last), shops (source kinds of bought orders), duplicate (a possible duplicate hint), open_tasks and overdue_tasks (members who see tasks).",
            "x-pl-description": "Osoby: id, imię, status, opiekun, tagi, ostatnia aktywność, dodano (created), zamówienia (liczba, wartość, pierwsze i ostatnie), shops (rodzaje źródeł opłaconych zamówień), duplicate (podejrzenie duplikatu), open_tasks i overdue_tasks (dla członków widzących zadania).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "per_page": {
            "description": "People per page.",
            "x-pl-description": "Osób na stronie.",
            "type": "integer"
          },
          "total": {
            "description": "All matching people.",
            "x-pl-description": "Wszystkie pasujące osoby.",
            "type": "integer"
          },
          "page": {
            "description": "Page number.",
            "x-pl-description": "Numer strony.",
            "type": "integer"
          }
        },
        "description": "A page of the Klienci list (25 people, or per_page) with the filters of the panel.",
        "x-pl-description": "Strona listy Klienci (25 osób albo per_page) z filtrami panelu."
      },
      "StatusList": {
        "type": "object",
        "properties": {
          "statuses": {
            "description": "Statuses: id, name, archived, sort, people.",
            "x-pl-description": "Statusy: id, name, archived, sort, people.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "description": "Internal statuses of people (never sent to Meta).",
        "x-pl-description": "Wewnętrzne statusy osób (nigdy nie trafiają do Mety)."
      },
      "StatusChange": {
        "type": "object",
        "properties": {
          "status": {
            "description": "Status id, or \"\" to clear.",
            "x-pl-description": "Identyfikator statusu albo \"\", by wyczyścić.",
            "type": "string"
          }
        },
        "required": [
          "status"
        ],
        "additionalProperties": false
      },
      "StatusResult": {
        "type": "object",
        "properties": {
          "status": {
            "description": "Status id (\"\" = none).",
            "x-pl-description": "Identyfikator statusu (\"\" = brak).",
            "type": "string"
          },
          "owner": {
            "description": "Owner id.",
            "x-pl-description": "Identyfikator opiekuna.",
            "type": "string"
          }
        },
        "description": "The person's status and owner after the change.",
        "x-pl-description": "Status i opiekun osoby po zmianie."
      },
      "History": {
        "type": "object",
        "properties": {
          "data": {
            "description": "History lines: kind, time, actor, summary, details.",
            "x-pl-description": "Wpisy: kind, time, actor, summary, details.",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "page": {
            "description": "Page number (`?page=`).",
            "x-pl-description": "Numer strony (`?page=`).",
            "type": "integer"
          },
          "more": {
            "description": "An older page exists.",
            "x-pl-description": "Istnieje starsza strona.",
            "type": "boolean"
          }
        },
        "description": "The person's history, newest first (the card's Historia).",
        "x-pl-description": "Historia osoby od najnowszych (Historia na karcie)."
      },
      "Diagnostics": {
        "type": "object",
        "properties": {},
        "description": "The last self-check: checks per area with status, detail and how to fix, counts per status and `verdict` (status error | warning | unknown — something could not be read | partial — some areas have nothing to check yet | ok; configured of areas; empty — the areas not set up).",
        "x-pl-description": "Ostatnia autodiagnostyka: sprawdzenia na obszar ze statusem, opisem i sposobem naprawy, liczby według statusu i `verdict` (status error | warning | unknown — czegoś nie udało się odczytać | partial — części obszarów nie ma jeszcze czego sprawdzić | ok; configured z areas; empty — obszary nieskonfigurowane)."
      },
      "DiagnosticsRun": {
        "type": "object",
        "properties": {
          "job": {
            "description": "The job (number, status).",
            "x-pl-description": "Zadanie (numer, status).",
            "type": "object"
          }
        },
        "description": "The self-check job that was queued or started.",
        "x-pl-description": "Uruchomione albo dodane do kolejki zadanie autodiagnostyki."
      },
      "ProductList": {
        "type": "object",
        "properties": {
          "products": {
            "description": "Products: id, external_id, title, price, sale_price, availability, stock, score 0–100, worst problem, issues, errors, warnings, origin_name, origin_kind, google {id, path, by person|own|auto|title|none, confidence, review — an automatic or by-title pick under 60 to check}, fixes {auto, manual}, stats of the period, trend (bought units per day, per week over 30 days).",
            "x-pl-description": "Produkty: id, external_id, tytuł, cena, cena promocyjna, dostępność, stan, ocena 0–100, najgorszy problem, problemy, errors, warnings, origin_name, origin_kind, google {id, path, by person|own|auto|title|none, confidence, review — wybór automatyczny albo po nazwie poniżej 60 do sprawdzenia}, fixes {auto, manual}, statystyki okresu, trend (kupione sztuki dziennie, tygodniowo powyżej 30 dni).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "total": {
            "description": "All matching products.",
            "x-pl-description": "Wszystkie pasujące produkty.",
            "type": "integer"
          },
          "summary": {
            "description": "Counts of the selection: errors, warnings, average score, problems by code.",
            "x-pl-description": "Liczby wyboru: błędy, ostrzeżenia, średnia ocena, problemy wg kodu.",
            "type": "object"
          },
          "per_page": {
            "description": "Products per page.",
            "x-pl-description": "Produktów na stronę.",
            "type": "integer"
          },
          "facets": {
            "description": "With facets=1: origins (id, name, kind, products), categories and brands (name, products; top 500), availability, google (set, review, none) and fixes (auto, manual) counts of the whole selection.",
            "x-pl-description": "Przy facets=1: pochodzenia (id, name, kind, products), kategorie i marki (name, products; 500 najliczniejszych) oraz liczby dostępności, google (set, review, none) i poprawek (auto, manual) całego wyboru.",
            "type": "object"
          }
        },
        "description": "A page of the Produkty list with a summary of the whole selection (and `facets` with facets=1).",
        "x-pl-description": "Strona listy Produkty z podsumowaniem całego wyboru (i `facets` przy facets=1)."
      },
      "Product": {
        "type": "object",
        "properties": {},
        "description": "One product: attributes and diagnosis as the shop gives it, then per feed what Basketly serves, what changed it (fixes, rules, flow blocks, manual fixes) and the diagnosis after; history and manual fixes; `origin` {id, name, kind} — the shop (kind = its platform) or the feed (kind feed) the product was read from.",
        "x-pl-description": "Jeden produkt: atrybuty i diagnoza ze sklepu, a dla każdego feedu to, co Basketly wysyła, co to zmieniło (poprawki, reguły, bloczki przepływu, ręczne poprawki) i diagnoza po zmianach; historia i ręczne poprawki; `origin` {id, name, kind} — sklep (kind = jego platforma) albo feed (kind feed), z którego produkt pochodzi."
      },
      "ProductsPerformance": {
        "type": "object",
        "properties": {},
        "description": "The period's picture of the catalogue: whether ad and shop data exist, products not shown / barely shown (under low_threshold impressions) / shown in Meta catalogue ads, the 10 best selling and the 10 most shown without a sale (each with its stats).",
        "x-pl-description": "Obraz katalogu w okresie: czy są dane z reklam i sklepu, produkty bez emisji / ze słabą emisją (poniżej low_threshold wyświetleń) / pokazywane w reklamach katalogowych Mety, 10 najlepiej sprzedających się i 10 najczęściej pokazywanych bez sprzedaży (każdy ze statystykami)."
      },
      "ProductStats": {
        "type": "object",
        "properties": {},
        "description": "One product's results of the period: totals (views, carts, checkouts, orders, units, revenue, impressions, clicks, spend) and a series per day.",
        "x-pl-description": "Wyniki jednego produktu w okresie: sumy (oglądania, koszyki, rozpoczęte zamówienia, zamówienia, sztuki, sprzedaż, wyświetlenia, kliknięcia, wydatek) i seria dzienna."
      },
      "CampaignProducts": {
        "type": "object",
        "properties": {},
        "description": "Catalogue products of a campaign or ad (or the whole account) of one platform (`platform`: meta, google_ads, microsoft_ads or tiktok), most shown first, at most 200 (`total` = all): impressions, clicks, ctr, spend, cpc from the platform's per-product report, and the shop's bought orders of the product in the period (`shop_orders`, `shop_revenue`, every source). Google Ads, Microsoft Ads and TikTok also give their own per-product conversions (`conversions`, `conversion_value`, `roas`, each platform's attribution window — never add them across platforms); they are null for Meta, which gives no purchases per product. `product` is null for an id missing from the catalogue.",
        "x-pl-description": "Produkty katalogu z kampanii albo reklamy (albo całego konta) jednej platformy (`platform`: meta, google_ads, microsoft_ads albo tiktok), najczęściej wyświetlane najpierw, najwyżej 200 (`total` = wszystkie): wyświetlenia, kliknięcia, ctr, wydatki, cpc z raportu platformy na produkt oraz opłacone zamówienia produktu w sklepie w okresie (`shop_orders`, `shop_revenue`, ze wszystkich źródeł). Google Ads, Microsoft Ads i TikTok podają też własne konwersje na produkt (`conversions`, `conversion_value`, `roas`, każda platforma w swoim oknie atrybucji — nie sumuj ich między platformami); dla Mety są null, bo Meta nie podaje zakupów na produkt. `product` jest null dla identyfikatora spoza katalogu."
      },
      "TemplatePerformance": {
        "type": "object",
        "properties": {},
        "description": "Each image template with the feeds whose rules or flow draw with it and the catalogue-ad results of those feeds' products in the period: products, shown (with impressions), impressions, clicks, ctr, spend. Counted for every product of such a feed, not only the ones the rule matched.",
        "x-pl-description": "Każdy szablon grafik z feedami, których reguły albo przepływ nim rysują, i wynikami produktów tych feedów w reklamach katalogowych w okresie: produkty, pokazane (z wyświetleniami), wyświetlenia, kliknięcia, ctr, wydatki. Liczone dla wszystkich produktów takiego feedu, nie tylko tych objętych regułą."
      },
      "ChannelTotals": {
        "type": "object",
        "properties": {},
        "description": "Every channel of a period in the shop's main currency next to the same number of days before. Three truth levels, never mixed: the platform's own figures (conversions, conversion_value, roas, cpa — its attribution window, named in `attribution`; never added across platforms), Basketly's last-click orders (baskety_orders, baskety_revenue, baskety_roas, baskety_cpo; one source per order, so `sources` shares add up to 1) and the shop (orders, revenue). `current` / `previous`: orders, revenue, average_order, other_currency_orders, spend_total (every channel's spend in the main currency), mer (shop revenue / spend_total), cost_per_order (spend_total / orders in the main currency), claims (the sum of every platform's own conversions — shown only next to the shop's orders, overlapping windows) and claims_ratio (claims / orders). `channels`: channel (meta, google_ads, microsoft_ads, tiktok, pinterest, openai_ads, email, comparison, other, direct, unknown), paid, connected, disconnected (every integration of the channel was disconnected; its figures were read before), reads (Basketly reads its campaign figures; TikTok and Pinterest once results reading is switched on for the connection), read_problem (why the platform refuses the read, e.g. a token without reporting permission; absent when none), attribution {code, text, read, click_days, view_days, engaged_days, mixed} (read = the window was read from the platform: Meta ad sets, Google's purchase conversion action, TikTok ad groups, Pinterest's fixed 30/30/1 days; mixed = groups use different windows, the most common is given), current / previous metrics (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa, baskety_orders, baskety_revenue, baskety_currency, baskety_roas, baskety_cpo), spend_share, order_share, mer (shop revenue / this channel's spend — not attribution), other_currency (spend in other currencies, left out of the line; `converted` = its amount in the main currency when the NBP conversion is on); manual lines (`manual`: true, `name`) are costs typed in by the team — spend only, counted in spend_total (`manual_spend`), MER and cost per order. `days`: day, orders, revenue, spend per channel (`manual` = typed-in costs). `fx` {enabled, rates [{currency, mid, date}], missing}: with the organisation's NBP conversion on, spend in other currencies joins spend_total (`fx_converted`) by the NBP table A average rate of the spend day; off = currencies are never converted. `shops`: kinds of the connected shops. `previous_coverage` {previous_from, since {shop, meta, google_ads…: the first day with data — the first paid order; a channel's first day of spend, Meta's first day read}, complete {same keys: the previous period is covered, with a margin of a tenth of the period, at most 3 days}, returning_complete (orders reach one more period, ≥ 30 days, before the previous one)}: comparisons with `previous` mean something only where it is complete — the conclusions and the verdict leave them out otherwise. Ratios are null without a divisor; every cost (cpc, cpm, cpa, baskety_cpo, cost_per_order) and ROAS is null without spend. `compare` and `comparison` — how a period that ends today is compared: `comparison` {mode whole|same_hour, until (HH:MM, organisation zone), previous_until (RFC 3339), spend_without_today, spend_to, previous_spend_to}. In same_hour the period ends today and the day is still going on, so the shop's figures of `previous` (orders, revenue, average order, buyers, Basketly's last-click orders, accepted purchases) end at the same hour of its last day, and every figure built on platform spend (spend, platform conversions and value, ROAS, MER, cost per order, claims, baskety_roas) is compared over whole days — today left out of the current period, the matching day out of `previous` (platforms report spend per day). `compare` holds the current figures to set against `previous` (the shop's as in `current`, spend and its ratios over whole days); `current` still counts today. Read every change as compare vs previous, never current vs previous; without spend_to (a period of today only) spend is not compared. mode whole: the period has ended, `compare` equals `current`.",
        "x-pl-description": "Każdy kanał w okresie w głównej walucie sklepu obok tylu samych dni wcześniej. Trzy poziomy prawdy, nigdy nie mieszane: liczby platformy (conversions, conversion_value, roas, cpa — jej okno atrybucji, nazwane w `attribution`; nigdy nie sumowane między platformami), zamówienia Basketly z ostatniego kliknięcia (baskety_orders, baskety_revenue, baskety_roas, baskety_cpo; jedno źródło na zamówienie, więc udziały `sources` sumują się do 1) i sklep (orders, revenue). `current` / `previous`: orders, revenue, average_order, other_currency_orders, spend_total (wydatki wszystkich kanałów w głównej walucie), mer (przychód sklepu / spend_total), cost_per_order (spend_total / zamówienia w głównej walucie), claims (suma własnych konwersji wszystkich platform — tylko obok zamówień sklepu, okna się nakładają) i claims_ratio (claims / orders). `channels`: channel (meta, google_ads, microsoft_ads, tiktok, pinterest, openai_ads, email, comparison, other, direct, unknown), paid, connected, disconnected (wszystkie integracje kanału są odłączone; liczby pobrano wcześniej), reads (Basketly odczytuje wyniki kampanii; TikTok i Pinterest po włączeniu odczytu wyników w połączeniu), read_problem (dlaczego platforma odmawia odczytu, np. token bez uprawnienia do raportów; brak, gdy nic), attribution {code, text, read, click_days, view_days, engaged_days, mixed} (read = okno odczytane z platformy: zestawy reklam Mety, akcja konwersji zakupu w Google, grupy reklam TikToka, stałe 30/30/1 dni Pinteresta; mixed = grupy mają różne okna, podane najczęstsze), metryki current / previous (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa, baskety_orders, baskety_revenue, baskety_currency, baskety_roas, baskety_cpo), spend_share, order_share, mer (przychód sklepu / wydatki tego kanału — nie atrybucja), other_currency (wydatki w innych walutach, poza wierszem; `converted` = kwota w głównej walucie przy włączonym przeliczaniu NBP); wiersze ręczne (`manual`: true, `name`) to koszty wpisane przez zespół — tylko wydatki, wliczane do spend_total (`manual_spend`), MER i kosztu zamówienia. `days`: day, orders, revenue, spend na kanał (`manual` = koszty wpisane ręcznie). `fx` {enabled, rates [{currency, mid, date}], missing}: przy włączonym przeliczaniu NBP wydatki w innych walutach wchodzą do spend_total (`fx_converted`) po średnim kursie NBP (tabela A) z dnia wydatku; wyłączone = waluty nigdy nie są przeliczane. `shops`: rodzaje podłączonych sklepów. `previous_coverage` {previous_from, since {shop, meta, google_ads…: pierwszy dzień z danymi — pierwsze opłacone zamówienie; pierwszy dzień wydatków kanału, dla Mety pierwszy dzień odczytu}, complete {te same klucze: poprzedni okres jest pokryty, z marginesem dziesiątej części okresu, najwyżej 3 dni}, returning_complete (zamówienia sięgają jeszcze jeden okres, ≥ 30 dni, przed poprzedni)}: porównanie z `previous` ma sens tylko tam, gdzie jest complete — wnioski i werdykt w przeciwnym razie go pomijają. Wskaźniki null bez dzielnika; każdy koszt (cpc, cpm, cpa, baskety_cpo, cost_per_order) i ROAS jest null bez wydatków. `compare` i `comparison` — jak porównujemy okres kończący się dziś: `comparison` {mode whole|same_hour, until (GG:MM, strefa organizacji), previous_until (RFC 3339), spend_without_today, spend_to, previous_spend_to}. Przy same_hour okres kończy się dziś, a dzień trwa, więc liczby sklepu w `previous` (zamówienia, przychód, średnie zamówienie, kupujący, zamówienia Basketly z ostatniego kliknięcia, zakupy przyjęte do wysyłki) kończą się o tej samej godzinie jego ostatniego dnia, a każda liczba oparta na wydatkach platform (wydatki, konwersje platform i ich wartość, ROAS, MER, koszt zamówienia, claims, baskety_roas) jest porównywana po pełnych dniach — bez dzisiejszego dnia w bieżącym okresie i odpowiadającego mu dnia w `previous` (platformy podają wydatki za dzień). `compare` to bieżące liczby do zestawienia z `previous` (sklepu jak w `current`, wydatki i ich wskaźniki po pełnych dniach); `current` nadal obejmuje dzisiejszy dzień. Każdą zmianę czytaj jako compare wobec previous, nigdy current wobec previous; bez spend_to (okres tylko z dzisiejszego dnia) wydatki nie są porównywane. mode whole: okres się skończył, `compare` równa się `current`."
      },
      "ChannelCreatives": {
        "type": "object",
        "properties": {},
        "description": "Creatives of one channel other than Meta (GET /creatives/report?channel=…): `ads` and, for Google Ads, `assets` (headlines, descriptions, images, YouTube videos; `field` names the role) — each with key, kind (ad | asset), id, name, format (image | video | text | carousel | shopping | responsive | app | other), title, body, thumbnail_url, video_id, campaign {id, name}, adgroup {id, name}, status, state (active | paused | removed), campaign_type, currency and metrics (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa as the platform reports them with its `attribution` window; baskety_orders / baskety_revenue for ads whose id an order's visit carried). `totals` per currency count ads only — assets repeat the money of the ads they ran in. `channels`: meta and every channel with creatives. Conversions of different channels are never added.",
        "x-pl-description": "Kreacje jednego kanału innego niż Meta (GET /creatives/report?channel=…): `ads` i, dla Google Ads, `assets` (nagłówki, teksty reklamy, obrazy, filmy YouTube; `field` nazywa rolę) — każda z key, kind (ad | asset), id, name, format (image | video | text | carousel | shopping | responsive | app | other), title, body, thumbnail_url, video_id, campaign {id, name}, adgroup {id, name}, status, state (active | paused | removed), campaign_type, currency i metrykami (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa według platformy z jej oknem `attribution`; baskety_orders / baskety_revenue dla reklam, których identyfikator niosła wizyta zamówienia). `totals` na walutę liczą tylko reklamy — zasoby powtarzają pieniądze reklam, w których działały. `channels`: meta i każdy kanał z kreacjami. Konwersji różnych kanałów nigdy nie sumujemy."
      },
      "ManualSpend": {
        "type": "object",
        "properties": {
          "id": {
            "description": "Entry id.",
            "x-pl-description": "Identyfikator wpisu.",
            "type": "string"
          },
          "channel": {
            "description": "Kind of cost: comparison (comparison sites), email (e-mail tool), agency, other.",
            "x-pl-description": "Rodzaj kosztu: comparison (porównywarki), email (narzędzie e-mail), agency (agencja), other (inne).",
            "type": "string",
            "enum": [
              "comparison",
              "email",
              "agency",
              "other"
            ]
          },
          "name": {
            "description": "What the cost is (required for other).",
            "x-pl-description": "Czego dotyczy koszt (wymagane dla other).",
            "type": "string"
          },
          "month": {
            "description": "Month YYYY-MM; the amount is spread evenly over its days.",
            "x-pl-description": "Miesiąc RRRR-MM; kwota rozkłada się równo na jego dni.",
            "type": "string"
          },
          "amount": {
            "description": "The month's amount.",
            "x-pl-description": "Kwota za miesiąc.",
            "type": "number"
          },
          "currency": {
            "description": "ISO currency code.",
            "x-pl-description": "Kod waluty ISO.",
            "type": "string"
          },
          "note": {
            "description": "Note.",
            "x-pl-description": "Notatka.",
            "type": "string"
          },
          "created": {
            "description": "Created.",
            "x-pl-description": "Utworzono.",
            "type": "string",
            "format": "date-time"
          },
          "updated": {
            "description": "Changed.",
            "x-pl-description": "Zmieniono.",
            "type": "string",
            "format": "date-time"
          }
        },
        "additionalProperties": false
      },
      "ManualSpendDeleted": {
        "type": "object",
        "properties": {
          "deleted": {
            "description": "Id of the removed entry.",
            "x-pl-description": "Identyfikator usuniętego wpisu.",
            "type": "string"
          }
        },
        "required": [
          "deleted"
        ],
        "additionalProperties": false
      },
      "ManualSpendList": {
        "type": "object",
        "properties": {},
        "description": "Costs outside ad platforms typed in by the team, newest month first (`rows`: ManualSpend), the shop's main `currency`, the kinds of cost (`channels`), `can_edit` (the caller may change them) and `fx` {enabled, can_change}: whether spend in other currencies is converted by the NBP rate into the blended total.",
        "x-pl-description": "Koszty spoza platform reklamowych wpisane przez zespół, od najnowszego miesiąca (`rows`: ManualSpend), główna waluta sklepu (`currency`), rodzaje kosztów (`channels`), `can_edit` (wywołujący może je zmieniać) i `fx` {enabled, can_change}: czy wydatki w innych walutach są przeliczane po kursie NBP do sumy łącznej."
      },
      "ManualSpendInput": {
        "type": "object",
        "properties": {
          "channel": {
            "description": "comparison, email, agency or other.",
            "x-pl-description": "comparison, email, agency albo other.",
            "type": "string",
            "enum": [
              "comparison",
              "email",
              "agency",
              "other"
            ]
          },
          "name": {
            "description": "What the cost is, up to 80 characters (required for other).",
            "x-pl-description": "Czego dotyczy koszt, do 80 znaków (wymagane dla other).",
            "type": "string"
          },
          "month": {
            "description": "YYYY-MM.",
            "x-pl-description": "RRRR-MM.",
            "type": "string"
          },
          "amount": {
            "description": "More than 0, at most 1 000 000 000.",
            "x-pl-description": "Więcej niż 0, najwyżej 1 000 000 000.",
            "type": "number"
          },
          "currency": {
            "description": "ISO code (default: the shop's main currency).",
            "x-pl-description": "Kod ISO (domyślnie główna waluta sklepu).",
            "type": "string"
          },
          "note": {
            "description": "Up to 500 characters.",
            "x-pl-description": "Do 500 znaków.",
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ManualSpendChange": {
        "type": "object",
        "properties": {
          "channel": {
            "description": "comparison, email, agency or other.",
            "x-pl-description": "comparison, email, agency albo other.",
            "type": "string",
            "enum": [
              "comparison",
              "email",
              "agency",
              "other"
            ]
          },
          "name": {
            "description": "What the cost is.",
            "x-pl-description": "Czego dotyczy koszt.",
            "type": "string"
          },
          "month": {
            "description": "YYYY-MM.",
            "x-pl-description": "RRRR-MM.",
            "type": "string"
          },
          "amount": {
            "description": "The month's amount.",
            "x-pl-description": "Kwota za miesiąc.",
            "type": "number"
          },
          "currency": {
            "description": "ISO code.",
            "x-pl-description": "Kod ISO.",
            "type": "string"
          },
          "note": {
            "description": "Note.",
            "x-pl-description": "Notatka.",
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ChannelReport": {
        "type": "object",
        "properties": {},
        "description": "Without `channel`: the ChannelTotals of the period. With `channel`: that channel's rows of `level` — id, name, status (the platform's own), state (active | paused | removed), type (search, shopping, performance_max, display, video, demand_gen, app, other; type_raw = the platform's value), currency and metrics (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa as the platform reports them; baskety_orders, baskety_revenue, baskety_currency, baskety_roas, baskety_cpo = Basketly's last-click orders of that campaign, matched by id or by a utm_campaign equal to its name) — `totals` per currency (current and previous), `levels` (the levels the channel has figures at), `attribution` {code, text, read, click_days, view_days, engaged_days, mixed}, `connected`, `disconnected` (every integration of the channel was disconnected; the rows were read before), `reads`, `read_problem`. TikTok and Pinterest rows come at the campaign, ad group and ad level once results reading is on. Meta's full report with video and ad sets' goals stays GET /campaigns/report. `totals` also carry `compare` and the answer `comparison` (as in ChannelTotals).",
        "x-pl-description": "Bez `channel`: ChannelTotals okresu. Z `channel`: wiersze tego kanału na poziomie `level` — id, name, status (platformy), state (active | paused | removed), type (search, shopping, performance_max, display, video, demand_gen, app, other; type_raw = wartość platformy), currency i metryki (spend, impressions, clicks, cpc, cpm, ctr, conversions, conversion_value, roas, cpa według platformy; baskety_orders, baskety_revenue, baskety_currency, baskety_roas, baskety_cpo = zamówienia Basketly z ostatniego kliknięcia w tę kampanię, dopasowane po id albo po utm_campaign równym jej nazwie) — `totals` na walutę (current i previous), `levels` (poziomy, na których kanał ma dane), `attribution` {code, text, read, click_days, view_days, engaged_days, mixed}, `connected`, `disconnected` (wszystkie integracje kanału są odłączone; wiersze pobrano wcześniej), `reads`, `read_problem`. TikTok i Pinterest mają wiersze kampanii, grup reklam i reklam po włączeniu odczytu wyników. Pełny raport Mety z wideo i celami zestawów to GET /campaigns/report. `totals` mają też `compare`, a odpowiedź `comparison` (jak w ChannelTotals)."
      },
      "ProductChannels": {
        "type": "object",
        "properties": {},
        "description": "One page of the product × channel matrix. `channels`: every channel of the period — channel, ads (the platform reported per-product figures; a channel without them has no figures at all, never zeros — Google Ads, Microsoft Ads and TikTok appear once their per-product reads store rows), per_product_conversions (false for Meta: Meta gives no purchases per product), attribution {code, text}, impressions, clicks, spend (main currency), products (with impressions), baskety_orders. `rows`: content_id, product (id, title, image_url, category, availability, price, currency), `channels` keyed by channel: impressions, clicks, spend, currency, ctr, cpc, conversions and conversion_value (the platform's own per product; null for Meta), baskety_orders (Basketly last-click orders of that channel containing the product), landing_orders (orders that landed on it through a tagged feed link), units_per_100_clicks (shop units against that channel's clicks — co-occurrence, not attribution), orders_per_100_clicks, impression_share and rank in the channel; `shop` (orders, units, revenue in the main currency, views, carts, stock, days_of_cover, availability); best_channel (most Basketly orders per 100 clicks with at least `min_clicks` clicks), spend_total and spend_split (main currency; spend is summable across channels), fp_orders and fp_split over every source key (unknown = no source). Never a column adding up platform conversions. `total`, `page`, `per_page`, `sort`, `channel`, `currency`.",
        "x-pl-description": "Jedna strona macierzy produkt × kanał. `channels`: każdy kanał okresu — channel, ads (platforma podała liczby na produkt; kanał bez nich nie ma żadnych liczb, nigdy zer — Google Ads, Microsoft Ads i TikTok pojawiają się, gdy ich odczyty na produkt zapiszą wiersze), per_product_conversions (false dla Mety: Meta nie podaje zakupów na produkt), attribution {code, text}, impressions, clicks, spend (główna waluta), products (z wyświetleniami), baskety_orders. `rows`: content_id, product (id, title, image_url, category, availability, price, currency), `channels` według kanału: impressions, clicks, spend, currency, ctr, cpc, conversions i conversion_value (własne liczby platformy na produkt; null dla Mety), baskety_orders (zamówienia Basketly z ostatniego kliknięcia w tym kanale zawierające produkt), landing_orders (zamówienia z wejścia na produkt przez otagowany link feedu), units_per_100_clicks (sztuki sklepu wobec kliknięć w tym kanale — współwystępowanie, nie atrybucja), orders_per_100_clicks, impression_share i rank w kanale; `shop` (orders, units, revenue w głównej walucie, views, carts, stock, days_of_cover, availability); best_channel (najwięcej zamówień Basketly na 100 kliknięć przy co najmniej `min_clicks` kliknięciach), spend_total i spend_split (główna waluta; wydatki można sumować między kanałami), fp_orders i fp_split po każdym kluczu źródła (unknown = bez źródła). Nigdy kolumna sumująca konwersje platform. `total`, `page`, `per_page`, `sort`, `channel`, `currency`."
      },
      "SalesReport": {
        "type": "object",
        "properties": {},
        "description": "`current` and `previous` blocks (orders, revenue, average_order, buyers, new_buyers, returning_buyers, repeat_rate, units, other_currency_orders, cancelled, spend, purchases, purchase_value, roas, mer, spend_per_order, accepted_purchases, accepted_share; ratios null without a divisor), `platforms` (Google Ads / Microsoft Ads, each as it reports itself: platform, spend, clicks, impressions, conversions, conversion_value, roas, mer, spend_per_order, other_currency_rows — never added to Meta), `currency`, `days` (day, orders, revenue, spend, platform_spend per platform), `weeks` (whole 7-day blocks back from the last day: week, until, orders, revenue, spend), `categories` (top-level catalogue category of the order lines, main currency: category, orders, units, revenue, share, previous_revenue, previous_units, change), the buyer split in each block (new_orders, new_revenue, new_average, returning_orders, returning_revenue, returning_average), `insights` (sales conclusions, see ReportInsights), `top_products` (content_id, name, orders, units, revenue), `weekly` (the Monday e-mail is on), `shops` (kinds of the connected shops: shoper, idosell, baselinker…), `channels` (every channel and the blended figures, see ChannelTotals; `current.spend`, `roas`, `mer` above stay Meta-only), `verdict` (Raporty → Przegląd: one sentence about the period from the blended figures — `kind` growth|decline|steady|no_spend|spend_without_sales|no_sales|no_data, `text` (Polish, English with Accept-Language: en), `tones` (the tone good|bad|neutral of each figure exactly as the text writes it), `numbers` (revenue, previous_revenue, revenue_change, orders, spend_total, spend_change, mer, previous_mer, mer_change — present when computable), `comparison` full|spend_partial|none (none: the shop's orders start inside the previous period, so nothing is compared; spend_partial: a channel's spend starts inside it, so spend and MER are not compared) with `data_since` (the first day of the data that cut the comparison, also named in the text)). The verdict's changes (revenue_change, spend_change, mer_change) and the sales conclusions compare `compare` with `previous`. `compare` and `comparison` — how a period that ends today is compared: `comparison` {mode whole|same_hour, until (HH:MM, organisation zone), previous_until (RFC 3339), spend_without_today, spend_to, previous_spend_to}. In same_hour the period ends today and the day is still going on, so the shop's figures of `previous` (orders, revenue, average order, buyers, Basketly's last-click orders, accepted purchases) end at the same hour of its last day, and every figure built on platform spend (spend, platform conversions and value, ROAS, MER, cost per order, claims, baskety_roas) is compared over whole days — today left out of the current period, the matching day out of `previous` (platforms report spend per day). `compare` holds the current figures to set against `previous` (the shop's as in `current`, spend and its ratios over whole days); `current` still counts today. Read every change as compare vs previous, never current vs previous; without spend_to (a period of today only) spend is not compared. mode whole: the period has ended, `compare` equals `current`.",
        "x-pl-description": "Bloki `current` i `previous` (orders, revenue, average_order, buyers, new_buyers, returning_buyers, repeat_rate, units, other_currency_orders, cancelled, spend, purchases, purchase_value, roas, mer, spend_per_order, accepted_purchases, accepted_share; wskaźniki null bez dzielnika), `platforms` (Google Ads / Microsoft Ads, każda według własnego raportu: platform, spend, clicks, impressions, conversions, conversion_value, roas, mer, spend_per_order, other_currency_rows — nigdy nie dodawane do Mety), `currency`, `days` (day, orders, revenue, spend, platform_spend na platformę), `weeks` (pełne bloki 7 dni od ostatniego dnia wstecz: week, until, orders, revenue, spend), `categories` (kategoria główna z katalogu dla pozycji zamówień, główna waluta: category, orders, units, revenue, share, previous_revenue, previous_units, change), podział kupujących w każdym bloku (new_orders, new_revenue, new_average, returning_orders, returning_revenue, returning_average), `insights` (wnioski o sprzedaży, zob. ReportInsights), `top_products` (content_id, name, orders, units, revenue), `weekly` (raport e-mailem w poniedziałek włączony), `shops` (rodzaje podłączonych sklepów: shoper, idosell, baselinker…), `channels` (każdy kanał i liczby łączne, zob. ChannelTotals; `current.spend`, `roas`, `mer` powyżej dotyczą tylko Mety), `verdict` (Raporty → Przegląd: jedno zdanie o okresie z liczb łącznych — `kind` growth|decline|steady|no_spend|spend_without_sales|no_sales|no_data, `text` (po polsku, po angielsku z Accept-Language: en), `tones` (ton good|bad|neutral każdej liczby dokładnie tak, jak zapisano ją w tekście), `numbers` (revenue, previous_revenue, revenue_change, orders, spend_total, spend_change, mer, previous_mer, mer_change — gdy da się je policzyć), `comparison` full|spend_partial|none (none: zamówienia sklepu zaczynają się w poprzednim okresie, więc nic nie jest porównywane; spend_partial: wydatki kanału zaczynają się w nim, więc wydatki i MER nie są porównywane) z `data_since` (pierwszy dzień danych, który uciął porównanie, podany też w tekście)). Zmiany w werdykcie (revenue_change, spend_change, mer_change) i wnioski o sprzedaży porównują `compare` z `previous`. `compare` i `comparison` — jak porównujemy okres kończący się dziś: `comparison` {mode whole|same_hour, until (GG:MM, strefa organizacji), previous_until (RFC 3339), spend_without_today, spend_to, previous_spend_to}. Przy same_hour okres kończy się dziś, a dzień trwa, więc liczby sklepu w `previous` (zamówienia, przychód, średnie zamówienie, kupujący, zamówienia Basketly z ostatniego kliknięcia, zakupy przyjęte do wysyłki) kończą się o tej samej godzinie jego ostatniego dnia, a każda liczba oparta na wydatkach platform (wydatki, konwersje platform i ich wartość, ROAS, MER, koszt zamówienia, claims, baskety_roas) jest porównywana po pełnych dniach — bez dzisiejszego dnia w bieżącym okresie i odpowiadającego mu dnia w `previous` (platformy podają wydatki za dzień). `compare` to bieżące liczby do zestawienia z `previous` (sklepu jak w `current`, wydatki i ich wskaźniki po pełnych dniach); `current` nadal obejmuje dzisiejszy dzień. Każdą zmianę czytaj jako compare wobec previous, nigdy current wobec previous; bez spend_to (okres tylko z dzisiejszego dnia) wydatki nie są porównywane. mode whole: okres się skończył, `compare` równa się `current`."
      },
      "ReportInsights": {
        "type": "object",
        "properties": {},
        "description": "Every conclusion of the period, most important first: severity, then `impact` (`insights`: rule, section sales|products|magnets|delivery|stock|feeds, severity warning|opportunity|positive|info, content_id or subject, product_id and image_url of the shop product, title, detail with the numbers, action (suggested step as text), numbers, `metrics` (2–3 key figures {label, value, tone good|bad|neutral} — the tone is decided by the server), `next_action` {kind exclude_in_feed|product_set|reorder|open_product|open_report_tab|open_feed, target (content_id, the feed id for open_feed, or the Raporty tab key: sales, products, magnets, stock, channels, delivery:unseen, delivery:concentration, delivery:stock — kept for older callers), label, href (open_report_tab only: the panel address of the tab since the tabs were renamed — `?widok=reports&zakladka=kanaly|produkty&produkty=trendy|produkty&produkty=kanaly|do-zakupow|magazyn|katalog-meta&emisja=…`)}, `tones` (figures of the title as written there with good|bad where the sign does not say it, e.g. 0 purchases), `impact` (money at stake in `impact_currency`, null when the rule has no amount), `key` (stable: rule + product or subject) and the caller's own `state` open|done|snoozed|dismissed with `state_until` for a snooze), `channels` on every conclusion (channel keys it is about, sorted; empty = the whole shop; channel rules channel_mer_change, channel_spend_up_mer_flat, channel_fp_roas_gap, channel_claims_overlap, channel_spend_no_orders, channel_untagged, product_channel_gap, product_unseen_in_channel in section `channels`; next_action kinds open_channel, open_channels, open_diagnostics target the channel key(s) or the self-check area), `sections` (open conclusions per section), `channels` (open conclusions per channel), `open`, `hidden` (done, snoozed or dismissed by the caller) and `rules` (every threshold). Rule-based and deterministic; no rule speaks below its minimum sample. Comparisons with the previous period (revenue_change, aov_change, category_change, returning_share, mer_change, channel_mer_change, channel_spend_up_mer_flat) stay silent unless the shop's orders and each spending channel cover the whole previous period (ChannelTotals.previous_coverage). product_unseen_in_channel: one conclusion per product and channel without impressions — `channels` = that channel and every channel that shows the product, the key follows the unseen channel only. product_channel_gap: also a sample on the weaker side (≥ product_channel_weak_min_clicks clicks and ≥ product_channel_min_expected orders expected at the better channel's rate); for a magnet in the weaker channel it is info with next_action open_report_tab magnets and `numbers.magnet` = 1. channel_fp_roas_gap: Basketly last click and the platforms' ROAS side by side; when the dearer channel is a reach channel (gap_reach_impression_share of paid impressions and gap_reach_claims_share of the platforms' claims) or has magnets, severity info and next_action open_report_tab magnets — compare with MER, do not cut budget on last click alone. `tones` also carry every key figure (metric) the title repeats, with the metric's tone. Texts are Polish here; the panel's English answers write money and ratios like en-GB (€675.00, PLN 1,234.50, ×3.25). When the period ends today, comparisons with the previous period read the shop's figures up to the same hour of the previous period's last day and spend, MER and ROAS over whole days without today (SalesReport.comparison) — an even pace of sales gives no fall in the morning.",
        "x-pl-description": "Wszystkie wnioski okresu, najważniejsze pierwsze: ważność, potem `impact` (`insights`: rule, section sales|products|magnets|delivery|stock|feeds, severity warning|opportunity|positive|info, content_id albo subject, product_id i image_url produktu ze sklepu, title, detail z liczbami, action (proponowane działanie jako tekst), numbers, `metrics` (2–3 kluczowe liczby {label, value, tone good|bad|neutral} — ton ustala serwer), `next_action` {kind exclude_in_feed|product_set|reorder|open_product|open_report_tab|open_feed, target (content_id, id feedu dla open_feed albo klucz zakładki Raportów: sales, products, magnets, stock, channels, delivery:unseen, delivery:concentration, delivery:stock — zachowany dla starszych klientów), label, href (tylko open_report_tab: adres zakładki w panelu po zmianie nazw zakładek — `?widok=reports&zakladka=kanaly|produkty&produkty=trendy|produkty&produkty=kanaly|do-zakupow|magazyn|katalog-meta&emisja=…`)}, `tones` (liczby z tytułu tak, jak są zapisane, z good|bad tam, gdzie znak tego nie mówi, np. 0 zakupów), `impact` (kwota, o którą chodzi, w `impact_currency`; null, gdy reguła nie ma kwoty), `key` (stały: reguła + produkt albo temat) i własny stan wywołującego `state` open|done|snoozed|dismissed z `state_until` przy odłożeniu), `channels` przy każdym wniosku (klucze kanałów, których dotyczy, posortowane; puste = cały sklep; reguły kanałowe channel_mer_change, channel_spend_up_mer_flat, channel_fp_roas_gap, channel_claims_overlap, channel_spend_no_orders, channel_untagged, product_channel_gap, product_unseen_in_channel w sekcji `channels`; rodzaje next_action open_channel, open_channels, open_diagnostics wskazują klucz(e) kanału albo obszar autodiagnostyki), `sections` (otwarte wnioski na sekcję), `channels` (otwarte wnioski na kanał), `open`, `hidden` (zrobione, odłożone albo odrzucone przez wywołującego) i `rules` (wszystkie progi). Reguły, nie model; żadna reguła nie działa poniżej minimalnej próby. Porównania z poprzednim okresem (revenue_change, aov_change, category_change, returning_share, mer_change, channel_mer_change, channel_spend_up_mer_flat) milczą, dopóki zamówienia sklepu i wydatki każdego wydającego kanału nie obejmują całego poprzedniego okresu (ChannelTotals.previous_coverage). product_unseen_in_channel: jeden wniosek na produkt i kanał bez wyświetleń — `channels` = ten kanał i każdy kanał, który produkt pokazuje, klucz zależy tylko od kanału bez wyświetleń. product_channel_gap: próba także po słabszej stronie (≥ product_channel_weak_min_clicks kliknięć i ≥ product_channel_min_expected zamówień oczekiwanych przy stopie lepszego kanału); dla magnesu w słabszym kanale to info z next_action open_report_tab magnets i `numbers.magnet` = 1. channel_fp_roas_gap: ostatnie kliknięcie Basketly i ROAS platform obok siebie; gdy droższy kanał jest zasięgowy (gap_reach_impression_share wyświetleń i gap_reach_claims_share deklaracji platform) albo ma magnesy, severity info i next_action open_report_tab magnets — porównaj z MER, nie tnij budżetu tylko po ostatnim kliknięciu. `tones` zawierają też każdą kluczową liczbę (metrykę) powtórzoną w tytule, z jej tonem. Teksty są tu po polsku; angielskie odpowiedzi panelu zapisują kwoty i krotności jak en-GB (€675.00, PLN 1,234.50, ×3.25). Gdy okres kończy się dziś, porównania z poprzednim okresem czytają liczby sklepu do tej samej godziny ostatniego dnia poprzedniego okresu, a wydatki, MER i ROAS po pełnych dniach bez dzisiejszego (SalesReport.comparison) — równe tempo sprzedaży nie daje rano spadku."
      },
      "InsightStateChange": {
        "type": "object",
        "properties": {
          "state": {
            "description": "done, snoozed, dismissed, or open to bring the conclusion back.",
            "x-pl-description": "done, snoozed, dismissed albo open, żeby przywrócić wniosek.",
            "type": "string",
            "enum": [
              "open",
              "done",
              "snoozed",
              "dismissed"
            ]
          },
          "until": {
            "description": "snoozed only: the day the conclusion comes back, YYYY-MM-DD (tomorrow up to a year; default 7 days from today).",
            "x-pl-description": "Tylko snoozed: dzień powrotu wniosku, RRRR-MM-DD (od jutra do roku; domyślnie 7 dni od dziś).",
            "type": "string",
            "format": "date"
          }
        },
        "required": [
          "state"
        ],
        "additionalProperties": false
      },
      "InsightState": {
        "type": "object",
        "properties": {
          "key": {
            "description": "The conclusion's key.",
            "x-pl-description": "Klucz wniosku.",
            "type": "string"
          },
          "state": {
            "description": "The state now.",
            "x-pl-description": "Stan po zmianie.",
            "type": "string",
            "enum": [
              "open",
              "done",
              "snoozed",
              "dismissed"
            ]
          },
          "until": {
            "description": "The day a snooze ends, or empty.",
            "x-pl-description": "Dzień końca odłożenia albo pusty.",
            "type": "string"
          }
        },
        "additionalProperties": false
      },
      "ProductTrajectories": {
        "type": "object",
        "properties": {},
        "description": "One page (`page`, `per_page`) of the products matching `q` and `pattern` (`matched`), out of every product with impressions, units or views (`total`; `listed` computed, at most 5000, `capped` when more): totals (impressions, clicks, ctr, spend, cpc, ad_currency from Meta's per-product breakdown; views, carts from the shop script; orders, units, revenue in `currency` from bought orders), impression_share, units_per_100_clicks, last_sale_days, impressions_trend / clicks_trend / units_trend (direction rising|falling|flat|thin, change = second half vs first half, slope per bucket, total), week_clicks / week_units (last 7 days vs the 7 before), pattern, series per bucket (`buckets`, `bucket` day|week), product (title, image_url, category…); `catalogue` totals, `patterns` counts over every listed product, `insights`. `trend_to`: the last day the trends and week-over-week changes read — the day before today when the period ends today (a day still going on never looks like a fall); the series and totals still count today.",
        "x-pl-description": "Jedna strona (`page`, `per_page`) produktów pasujących do `q` i `pattern` (`matched`) spośród wszystkich produktów z wyświetleniami, sprzedażą albo odsłonami (`total`; `listed` policzone, najwyżej 5000, `capped`, gdy więcej): sumy (wyświetlenia, kliknięcia, ctr, wydatki, cpc, ad_currency z rozbicia Mety na produkty; oglądania, koszyki ze skryptu sklepu; zamówienia, sztuki, przychód w `currency` z opłaconych zamówień), impression_share, units_per_100_clicks, last_sale_days, impressions_trend / clicks_trend / units_trend (direction rising|falling|flat|thin, change = druga połowa okresu wobec pierwszej, slope na przedział, total), week_clicks / week_units (ostatnie 7 dni wobec 7 wcześniejszych), pattern, series na przedział (`buckets`, `bucket` day|week), product (tytuł, zdjęcie, kategoria…); sumy `catalogue`, liczby `patterns` ze wszystkich policzonych produktów, `insights`. `trend_to`: ostatni dzień, który czytają trendy i zmiany tydzień do tygodnia — dzień przed dzisiejszym, gdy okres kończy się dziś (trwający dzień nigdy nie wygląda na spadek); serie i sumy nadal obejmują dzisiejszy dzień."
      },
      "ProductTrajectory": {
        "type": "object",
        "properties": {},
        "description": "One product: `product` (as in ProductTrajectories), `days` (day, impressions, clicks, spend, views, units, revenue), `catalogue`, `insights` of the product.",
        "x-pl-description": "Jeden produkt: `product` (jak w ProductTrajectories), `days` (day, impressions, clicks, spend, views, units, revenue), `catalogue`, `insights` produktu."
      },
      "ProductMagnets": {
        "type": "object",
        "properties": {},
        "description": "Products looked at or clicked but rarely bought while the same people buy other products. `rows`: content_id, product, visits reading (viewers, visit_orders, visit_self, visit_other, visit_other_share, visit_self_share — script visitors whose order is linked to their visit), ads reading (ad_clicks, ad_orders, ad_self, ad_other, ad_other_share — orders whose Basketly ad source is an ad in which the product got clicks, weighted by its click share), own_orders, others (products bought instead), magnet, method visits|ads|both; has_visits, has_linked_orders, has_ad_orders, thresholds, magnets, insights. Co-occurrence, not proof of cause.",
        "x-pl-description": "Produkty oglądane albo klikane, ale rzadko kupowane, gdy ci sami ludzie kupują inne produkty. `rows`: content_id, product, odczyt z wizyt (viewers, visit_orders, visit_self, visit_other, visit_other_share, visit_self_share — odwiedzający ze skryptu, których zamówienie jest powiązane z wizytą), odczyt z reklam (ad_clicks, ad_orders, ad_self, ad_other, ad_other_share — zamówienia, których źródłem reklamowym w Basketly jest reklama z kliknięciami produktu, ważone jego udziałem w kliknięciach), own_orders, others (produkty kupione zamiast), magnet, method visits|ads|both; has_visits, has_linked_orders, has_ad_orders, thresholds, magnets, insights. Współwystępowanie, nie dowód przyczyny."
      },
      "StockSignals": {
        "type": "object",
        "properties": {},
        "description": "Raporty → Zatowarowanie: products with stock from the shop and how long it lasts. `rows` (most urgent first, up to 2000): content_id, product, brand, source, stock (at the last product read, `synced_at`), sold_since_sync, stock_estimate_now (Basketly's estimate = stock at the read − units in not cancelled orders placed since), units_7/14/28, velocity_7/14/28, velocity_basis 14|28|'' (3 units needed), velocity_used (raised to velocity_7 when demand rises), velocity_adjusted, days_of_cover, stockout_eta (linear extrapolation), sell_through (period units / (units + stock), approximation without goods received), reorder_point (velocity × lead time × 1.2), suggested_qty (velocity × (lead time + 30) − stock), level sold_out|critical|warning|watch|ok|overstock|thin, base_level (before the rising bump), price, revenue_at_risk (velocity × lead time × price, critical and sold out), units, revenue, impressions, clicks, impression_rank, in_ads, demand (clicks, carts, impressions week over week, rank, previous_rank, rank_change, rising, rising_by), daily_units (14 days). Also lead_time_days, lead_time_source org|default|query, has_stock, has_sales, has_ads, has_shop_events, stock_read_at, tracked, untracked, levels, tiles, total, rules, insights.",
        "x-pl-description": "Raporty → Zatowarowanie: produkty ze stanem ze sklepu i na ile on wystarczy. `rows` (najpilniejsze pierwsze, do 2000): content_id, product, brand, source, stock (z ostatniego odczytu produktów, `synced_at`), sold_since_sync, stock_estimate_now (szacunek Basketly = stan z odczytu − sztuki z nieanulowanych zamówień złożonych od tego czasu), units_7/14/28, velocity_7/14/28, velocity_basis 14|28|'' (potrzeba 3 sztuk), velocity_used (podniesione do velocity_7, gdy popyt rośnie), velocity_adjusted, days_of_cover, stockout_eta (ekstrapolacja liniowa), sell_through (sztuki okresu / (sztuki + stan), przybliżenie bez przyjęć magazynowych), reorder_point (tempo × czas dostawy × 1,2), suggested_qty (tempo × (czas dostawy + 30) − stan), level sold_out|critical|warning|watch|ok|overstock|thin, base_level (przed podbiciem za rosnący popyt), price, revenue_at_risk (tempo × czas dostawy × cena, krytyczne i wyprzedane), units, revenue, impressions, clicks, impression_rank, in_ads, demand (kliknięcia, koszyki, wyświetlenia tydzień do tygodnia, rank, previous_rank, rank_change, rising, rising_by), daily_units (14 dni). Do tego lead_time_days, lead_time_source org|default|query, has_stock, has_sales, has_ads, has_shop_events, stock_read_at, tracked, untracked, levels, tiles, total, rules, insights."
      },
      "FeedOrders": {
        "type": "object",
        "properties": {},
        "description": "Orders whose visit landed on a tagged catalogue link (Basketly's reading from the shop script, not Meta's purchases). `feeds`: id, name, format, tagging, orders, revenue (main currency), self (bought the landing product), other (only other products), other_share, products, clicks (of the feed's products, Meta breakdown), orders_per_100_clicks, top (landing products). `products`: content_id, product, feeds, orders, self, other, other_share, revenue, clicks, orders_per_100_clicks, shop_orders, tagged_share. Also has_tagging, has_shop_events, has_tagged_orders, orders, revenue, self, other, insights.",
        "x-pl-description": "Zamówienia, których wizyta trafiła przez otagowany link katalogu (odczyt Basketly ze skryptu sklepu, nie zakupy według Mety). `feeds`: id, name, format, tagging, orders, revenue (główna waluta), self (kupiono produkt z wejścia), other (tylko inne produkty), other_share, products, clicks (produktów feedu, podział Mety), orders_per_100_clicks, top (produkty wejścia). `products`: content_id, product, feeds, orders, self, other, other_share, revenue, clicks, orders_per_100_clicks, shop_orders, tagged_share. Do tego has_tagging, has_shop_events, has_tagged_orders, orders, revenue, self, other, insights."
      },
      "ProductSetHealth": {
        "type": "object",
        "properties": {},
        "description": "Product set health of the chosen Meta catalogues (optional catalogue connection; `connected` false = none chosen). `sets`: set_id, name, catalog_id, catalog_name, product_count (Meta's count), members and members_read (membership read for sets promoted by ad sets), in_stock, in_stock_pct, approved_pct, rejected_pct, pending_pct (null when membership was not read), spend and currency (spend of the ad sets promoting the set in the period, as Meta reports it), ad_sets, active_ad_sets, warnings (empty, few_in_stock, rejected); `diagnostics` (Meta's catalogue diagnostics: catalog_id, catalog_name, kind, severity MUST_FIX|OPPORTUNITY|…, title, description, affected); `catalogs` (chosen catalogues and their last read), `totals`, `thresholds`.",
        "x-pl-description": "Zdrowie zestawów produktów wybranych katalogów Meta (opcjonalne połączenie katalogu; `connected` false = nie wybrano żadnego). `sets`: set_id, name, catalog_id, catalog_name, product_count (liczba Mety), members i members_read (skład odczytany dla zestawów używanych przez zestawy reklam), in_stock, in_stock_pct, approved_pct, rejected_pct, pending_pct (null, gdy skład nie był odczytany), spend i currency (wydatki zestawów reklam promujących zestaw w okresie, jak raportuje Meta), ad_sets, active_ad_sets, warnings (empty, few_in_stock, rejected); `diagnostics` (diagnostyka katalogu Mety: catalog_id, catalog_name, kind, severity MUST_FIX|OPPORTUNITY|…, title, description, affected); `catalogs` (wybrane katalogi i ich ostatni odczyt), `totals`, `thresholds`."
      },
      "MetaCatalogState": {
        "type": "object",
        "properties": {},
        "description": "The optional Meta catalogue connection: `enabled` (Meta login configured on the server), `catalog_config` (a separate catalogue login configuration exists), `accounts` (Meta logins: id, label, status) and `catalogs` (chosen catalogues: catalog_id, name, business, account, account_label, status waiting|ok|error|no_permission, error, products, sets, diagnostics, truncated, synced_at). Connecting and choosing stay in the panel.",
        "x-pl-description": "Opcjonalne połączenie katalogu Meta: `enabled` (logowanie Meta skonfigurowane na serwerze), `catalog_config` (osobna konfiguracja logowania dla katalogu), `accounts` (logowania Meta: id, label, status) i `catalogs` (wybrane katalogi: catalog_id, name, business, account, account_label, status waiting|ok|error|no_permission, error, products, sets, diagnostics, truncated, synced_at). Łączenie i wybór zostają w panelu."
      },
      "MetaCatalogStatus": {
        "type": "object",
        "properties": {},
        "description": "`connected` and `products`: per requested content_id — in_catalog, and when found catalog_id, review_status (approved|pending|rejected|outdated), rejections (Meta's reasons and item errors), availability, visibility, in_active_set (in a product set promoted by an active ad set), sets_known (membership of every such set read completely), sets (names) and reason (meta_rejected|meta_pending|not_in_active_set|\"\"). Data as of the last catalogue read.",
        "x-pl-description": "`connected` i `products`: dla każdego content_id — in_catalog, a gdy znaleziony catalog_id, review_status (approved|pending|rejected|outdated), rejections (powody Mety i błędy produktu), availability, visibility, in_active_set (w zestawie produktów promowanym przez aktywny zestaw reklam), sets_known (skład każdego takiego zestawu odczytany w całości), sets (nazwy) i reason (meta_rejected|meta_pending|not_in_active_set|\"\"). Dane z ostatniego odczytu katalogu."
      },
      "UnseenProducts": {
        "type": "object",
        "properties": {},
        "description": "Products that could be shown in Meta catalogue ads and were not. `level`: feed (served by a Basketly feed Meta can read — Google RSS or CSV — after its rules or canvas) or probable (no such feed; every active product counts); `meta_catalog` true = a chosen Meta catalogue was read, so reasons include meta_rejected, meta_pending and not_in_active_set. `feeds` (id, name, output, members, inputs), `summary` (products, eligible, unseen, unseen_share, low, shown, unseen_with_sales, frozen_value, eligible_stock_value, reasons per reason, no_impressions = every product without impressions, low_all = every barely shown product; the default list = no_impressions + low_all), `catalogue` (impressions, clicks, spend, ad_currency, products shown), `rows` (content_id, product, reason not_in_feed|excluded_by_rule|out_of_stock|meta_error_check|meta_rejected|meta_pending|pending_sync|not_in_active_set|not_picked or empty when shown, reason_detail, reason_feed, eligible, feeds, in_feed_since, days_in_feed, impressions, clicks, spend, ad_currency, last_impression_day, last_impression_days, exposure none|low|shown, views, carts, units, revenue, stock, stock_value, meta_errors, meta_warnings), total, page, per_page, facets (categories, brands), has_ads, has_feed, has_stock, has_shop_events, has_sales, low_threshold, insights (unseen_sellers, unseen_share, frozen_stock). Zero impressions = absent from the per-product breakdown of the connected ad accounts, not a rejection.",
        "x-pl-description": "Produkty, które mogły być pokazane w reklamach katalogowych Mety, a nie były. `level`: feed (serwowany przez feed Basketly czytany przez Metę — Google RSS albo CSV — po regułach lub kanwie) albo probable (brak takiego feedu; liczy się każdy aktywny produkt); `meta_catalog` true = odczytano wybrany katalog Meta, więc przyczyny obejmują meta_rejected, meta_pending i not_in_active_set. `feeds` (id, name, output, members, inputs), `summary` (products, eligible, unseen, unseen_share, low, shown, unseen_with_sales, frozen_value, eligible_stock_value, reasons według przyczyny, no_impressions = wszystkie produkty bez wyświetleń, low_all = wszystkie słabo wyświetlane; domyślna lista = no_impressions + low_all), `catalogue` (impressions, clicks, spend, ad_currency, products z wyświetleniami), `rows` (content_id, product, reason not_in_feed|excluded_by_rule|out_of_stock|meta_error_check|meta_rejected|meta_pending|pending_sync|not_in_active_set|not_picked albo pusty, gdy wyświetlany, reason_detail, reason_feed, eligible, feeds, in_feed_since, days_in_feed, impressions, clicks, spend, ad_currency, last_impression_day, last_impression_days, exposure none|low|shown, views, carts, units, revenue, stock, stock_value, meta_errors, meta_warnings), total, page, per_page, facets (categories, brands), has_ads, has_feed, has_stock, has_shop_events, has_sales, low_threshold, insights (unseen_sellers, unseen_share, frozen_stock). Zero wyświetleń = brak w podziale na produkty podłączonych kont reklamowych, nie odrzucenie."
      },
      "StockAds": {
        "type": "object",
        "properties": {},
        "description": "Sold-out products still shown and products back in stock but not shown. `sold_out` (content_id, product, out_since, back_on, currently_out, overlap_days, impressions, clicks, spend, ad_currency, lag_days, last_shown_day, still_shown, feeds), `back_in_stock` (content_id, product, back_on, days_since, out_days, impressions_before, last_shown_day, units_since, views_since, feeds), `summary` (sold_out_shown, spend, impressions, clicks, spend_share, still_shown, lag_median, lag_samples, back_unseen, currently_out, availability_changes), `catalogue`, latest_day, back_in_stock_days, has_ads, has_history, has_feed, has_stock, insights (sold_out_spend, back_in_stock_unseen). Products are read nightly, the breakdown every 6 hours.",
        "x-pl-description": "Wyprzedane produkty wciąż wyświetlane i produkty, które wróciły na stan bez emisji. `sold_out` (content_id, product, out_since, back_on, currently_out, overlap_days, impressions, clicks, spend, ad_currency, lag_days, last_shown_day, still_shown, feeds), `back_in_stock` (content_id, product, back_on, days_since, out_days, impressions_before, last_shown_day, units_since, views_since, feeds), `summary` (sold_out_shown, spend, impressions, clicks, spend_share, still_shown, lag_median, lag_samples, back_unseen, currently_out, availability_changes), `catalogue`, latest_day, back_in_stock_days, has_ads, has_history, has_feed, has_stock, insights (sold_out_spend, back_in_stock_unseen). Produkty są czytane co noc, podział na produkty co 6 godzin."
      },
      "DeliveryConcentration": {
        "type": "object",
        "properties": {},
        "description": "Delivery concentration of one scope and period. `scope` {kind, id, name}; `options` (accounts, campaigns, adsets, ads with impressions, to pick a scope); `header` (impressions, clicks, ctr, cpc, spend, currency, meta_purchases and meta_purchase_value of the scope's catalogue ads as Meta reports them per ad, shop units and revenue, products shown); `rows` 1…50 (rank, content_id, product with availability and stock, impressions, impression_share, cumulative_share, clicks, ctr, cpc, spend, spend_share, units, revenue, units_per_100_clicks, first_seen, days_top1) and `rest`; `metrics` (enough, top1_share, top5_share, top10_share, gini, hhi, effective_products = 1/HHI, spend_gini, click_gini, shown_products, eligible_products with eligible_basis (feed|probable, the reading of /reports/unseen), shown_outside_eligible (shown products not eligible today — why shown can exceed eligible), rank1_changes — null below 1000 impressions or 10 products); `bucket` week|day, `series_products` (top 5), `buckets` (key, impressions, top per product, rest, products, top1_share, top5_share, gini, effective_products, rank1, stockouts); `stockouts` (content_id, product, day, rank_before, share_before, windows of 7 and 14 days: before/after impressions, clicks, ctr, spend, meta_purchases, units, changes per day, lost_share, new_rank1, recovery_days, gainers); `products`, `insights` (section delivery), `rules`. Meta gives no purchases per product; the before/after is a comparison of periods, not proof of cause.",
        "x-pl-description": "Koncentracja emisji jednego zakresu i okresu. `scope` {kind, id, name}; `options` (konta, kampanie, zestawy i reklamy z wyświetleniami, do wyboru zakresu); `header` (wyświetlenia, kliknięcia, ctr, cpc, wydatki, waluta, meta_purchases i meta_purchase_value reklam katalogowych zakresu wg Mety na reklamę, sztuki i przychód sklepu, liczba pokazanych produktów); `rows` 1…50 (rank, content_id, produkt z dostępnością i stanem, impressions, impression_share, cumulative_share, clicks, ctr, cpc, spend, spend_share, units, revenue, units_per_100_clicks, first_seen, days_top1) i `rest`; `metrics` (enough, top1_share, top5_share, top10_share, gini, hhi, effective_products = 1/HHI, spend_gini, click_gini, shown_products, eligible_products z eligible_basis (feed|probable, odczyt jak w /reports/unseen), shown_outside_eligible (pokazane produkty, które dziś nie spełniają warunków — dlatego pokazanych bywa więcej niż dostępnych), rank1_changes — null poniżej 1000 wyświetleń albo 10 produktów); `bucket` week|day, `series_products` (pierwsza piątka), `buckets` (key, impressions, top na produkt, rest, products, top1_share, top5_share, gini, effective_products, rank1, stockouts); `stockouts` (content_id, produkt, dzień, rank_before, share_before, okna 7 i 14 dni: przed/po wyświetlenia, kliknięcia, ctr, wydatki, meta_purchases, sztuki, zmiany dzienne, lost_share, new_rank1, recovery_days, gainers); `products`, `insights` (sekcja delivery), `rules`. Meta nie podaje zakupów na produkt; przed/po to zestawienie okresów, nie dowód przyczyny."
      },
      "AutomationList": {
        "type": "object",
        "properties": {},
        "description": "`automations`: id, name, active, trigger_type (e.g. trigger.order_paid, trigger.buyer_inactive, trigger.shop_alert), version, template, updated, created, author (who created it), last_run {status, created, …} or null, errors_24h (failed steps, 24 h), runs_30d, sent_30d (SMS, e-mails and webhooks sent), failed_30d (failed steps) — all of the last 30 days without test runs —, running (runs in progress), channels (action node types of the graph, e.g. action.sms).",
        "x-pl-description": "`automations`: id, nazwa, active, trigger_type (np. trigger.order_paid, trigger.buyer_inactive, trigger.shop_alert), wersja, szablon, updated, created, author (kto ją utworzył), last_run {status, created, …} albo null, errors_24h (błędne kroki, 24 h), runs_30d, sent_30d (wysłane SMS-y, e-maile i webhooki), failed_30d (błędne kroki) — wszystko z ostatnich 30 dni bez uruchomień testowych —, running (uruchomienia w toku), channels (typy węzłów działań w grafie, np. action.sms)."
      },
      "SegmentList": {
        "type": "object",
        "properties": {},
        "description": "`segments` (id, name, filters {parameter: [values]}, count — -1 when a filter no longer validates —, audience {account, id, status syncing|ok|error|off, error, size, synced_at} — the Meta custom audience —, klaviyo {integration, list, list_name, status syncing|ok|error|off, error, size, synced_at} — the Klaviyo list; people are only added to it by e-mail, their Klaviyo marketing consent is never changed) and `presets` (key new_buyers|one_order|returning|lapsed|never_bought, filters, count).",
        "x-pl-description": "`segments` (id, nazwa, filters {parametr: [wartości]}, count — -1, gdy filtr przestał być poprawny —, audience {account, id, status syncing|ok|error|off, error, size, synced_at} — grupa odbiorców Meta —, klaviyo {integration, list, list_name, status syncing|ok|error|off, error, size, synced_at} — lista Klaviyo; osoby są tylko dopisywane po e-mailu, ich zgoda marketingowa w Klaviyo się nie zmienia) i `presets` (key new_buyers|one_order|returning|lapsed|never_bought, filters, count)."
      },
      "ConversionBalance": {
        "type": "object",
        "properties": {},
        "description": "The purchase balance of the period (days in the organisation's zone, by the purchase's day): `rows` per day (orders, revenue in `currency`, events, `sends` per destination key: accepted, failed, waiting), `destinations` (key, provider meta|ga4|tiktok|pinterest|klaviyo|openai_ads|google_ads|microsoft_ads, name), `totals` and `problems` (destination, error, count; at most 5).",
        "x-pl-description": "Bilans zakupów okresu (dni w strefie organizacji, wg dnia zakupu): `rows` na dzień (zamówienia, przychód w `currency`, zdarzenia, `sends` na klucz miejsca docelowego: przyjęte, błędy, czeka), `destinations` (klucz, provider meta|ga4|tiktok|pinterest|klaviyo|openai_ads|google_ads|microsoft_ads, nazwa), `totals` i `problems` (miejsce, błąd, liczba; najwyżej 5)."
      },
      "UnseenFlow": {
        "type": "object",
        "properties": {
          "days": {
            "description": "Period: 7, 14, 30 or 90 days.",
            "x-pl-description": "Okres: 7, 14, 30 albo 90 dni.",
            "type": "integer",
            "enum": [
              7,
              14,
              30,
              90
            ]
          },
          "below": {
            "description": "Impressions under which a product counts as barely shown (≥ 1).",
            "x-pl-description": "Liczba wyświetleń, poniżej której produkt ma słabą emisję (≥ 1).",
            "type": "number"
          }
        },
        "required": [
          "days",
          "below"
        ],
        "additionalProperties": false
      },
      "ProductOverrides": {
        "type": "object",
        "properties": {
          "overrides": {
            "description": "Attribute → value typed by hand; they win in every feed and survive the next read. \"\" removes the attribute. Replaces all manual fixes (send the ones to keep). `id` cannot be changed.",
            "x-pl-description": "Atrybut → wartość wpisana ręcznie; wygrywa w każdym feedzie i zostaje po kolejnym pobraniu. \"\" usuwa atrybut. Zastępuje wszystkie ręczne poprawki (wyślij te, które mają zostać). `id` nie można zmienić.",
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          }
        },
        "required": [
          "overrides"
        ],
        "additionalProperties": false
      },
      "FeedList": {
        "type": "object",
        "properties": {
          "feeds": {
            "description": "Feeds as in GET /feeds/{id} without fields, plus `category_coverage` {covered, products}: products that leave the feed with a Google category (as on the Kategorie Google tab), null when it cannot be counted.",
            "x-pl-description": "Feedy jak w GET /feeds/{id}, bez listy pól, z `category_coverage` {covered, products}: produkty, które wychodzą z feedu z kategorią Google (jak w zakładce Kategorie Google), null, gdy nie da się policzyć.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "description": "The organisation's feeds (up to 20).",
        "x-pl-description": "Feedy organizacji (do 20)."
      },
      "Feed": {
        "type": "object",
        "properties": {},
        "description": "A feed: input (url, file, source, feeds or flow; for a shop `source_name` and `source_platform`, the shop kind such as shoper), state, products, output format and address, automatic fixes, rules and — for a flow — the canvas `graph`, `link_tagging` (enabled, preset, params, ads_redirect, the Basketly `marker` and the `presets` with their parameters); with `fields` (attributes and how many products fill them) on GET /feeds/{id}.",
        "x-pl-description": "Feed: wejście (url, file, source, feeds albo flow; dla sklepu `source_name` i `source_platform`, rodzaj sklepu, np. shoper), stan, produkty, format i adres wyjścia, automatyczne poprawki, reguły i — dla przepływu — płótno `graph`, `link_tagging` (enabled, preset, params, ads_redirect, znacznik Basketly `marker` i zestawy `presets` z ich parametrami); z `fields` (atrybuty i ile produktów je wypełnia) w GET /feeds/{id}."
      },
      "LinkTagging": {
        "type": "object",
        "properties": {
          "enabled": {
            "description": "Tag served product links (the last step before serving). New feeds start on; feeds made before the setting stay off until switched on.",
            "x-pl-description": "Tagowanie linków produktów w feedzie wyjściowym (ostatni krok przed podaniem). Nowe feedy startują włączone; feedy sprzed tego ustawienia zostają wyłączone, dopóki ktoś nie włączy.",
            "type": "boolean"
          },
          "preset": {
            "description": "marker = only Basketly's bk_f/bk_pid; meta, google, ceneo = channel parameters; custom = your own. A named preset without `params` takes its own parameters.",
            "x-pl-description": "marker = tylko znacznik Basketly bk_f/bk_pid; meta, google, ceneo = parametry kanału; custom = własne. Zestaw bez `params` bierze swoje parametry.",
            "type": "string",
            "enum": [
              "marker",
              "meta",
              "google",
              "ceneo",
              "custom"
            ]
          },
          "params": {
            "description": "Query template added to links, e.g. utm_source=facebook&utm_content={id}. Placeholders {id}, {item_group_id}, {brand}, {product_type}, {feed} (the feed's name as a slug) are filled from the product and URL-encoded; any other {…} or {{…}} is a channel macro (Google ValueTrack, Meta) served untouched. bk_f/bk_pid are reserved. Parameters a link already has are never replaced.",
            "x-pl-description": "Szablon parametrów dopisywanych do linków, np. utm_source=facebook&utm_content={id}. Znaczniki {id}, {item_group_id}, {brand}, {product_type}, {feed} (nazwa feedu jako slug) wypełnia produkt (zakodowane w URL); każde inne {…} albo {{…}} to makro kanału (ValueTrack Google, Meta) podawane bez zmian. bk_f/bk_pid są zarezerwowane. Parametrów, które link już ma, nigdy nie zastępujemy.",
            "type": "string"
          },
          "ads_redirect": {
            "description": "Google: the parameters go only into ads_redirect (Shopping ad clicks; built from link when the product has none), link and mobile_link get only the marker. Ignored for Ceneo.",
            "x-pl-description": "Google: parametry trafiają tylko do ads_redirect (kliknięcia reklam produktowych; z linku, gdy produkt go nie ma), link i mobile_link dostają tylko znacznik. Pomijane dla Ceneo.",
            "type": "boolean"
          }
        },
        "additionalProperties": false
      },
      "LinkTaggingPreview": {
        "type": "object",
        "properties": {},
        "description": "One served product (`product_id`, `title`, `link`; `example` = true when the feed serves no product with a link yet) with `tagged_link` and, when they change, `tagged_mobile_link`, `tagged_ads_redirect`, `tagged_canonical_link`; `enabled` (the saved switch) and `served_link` / `served_ads_redirect` = what the feed serves for that product now with the saved setting (the shop link when tagging is off); the checked `setting`; `warnings`: google_autotagging, meta_ad_params, meta_macros, valuetrack_in_link.",
        "x-pl-description": "Jeden produkt z feedu (`product_id`, `title`, `link`; `example` = true, gdy feed nie podaje jeszcze produktu z linkiem) z `tagged_link` i, gdy się zmieniają, `tagged_mobile_link`, `tagged_ads_redirect`, `tagged_canonical_link`; `enabled` (zapisany przełącznik) i `served_link` / `served_ads_redirect` = co feed podaje teraz dla tego produktu z zapisanym ustawieniem (przy wyłączonym tagowaniu link ze sklepu); sprawdzone ustawienie `setting`; ostrzeżenia `warnings`: google_autotagging, meta_ad_params, meta_macros, valuetrack_in_link."
      },
      "FeedCreate": {
        "type": "object",
        "properties": {
          "name": {
            "description": "2–120 characters.",
            "x-pl-description": "2–120 znaków.",
            "type": "string"
          },
          "input": {
            "description": "Where products come from.",
            "x-pl-description": "Skąd brać produkty.",
            "type": "string",
            "enum": [
              "url",
              "source",
              "feeds",
              "flow"
            ]
          },
          "url": {
            "description": "input=url: the feed address (http/https).",
            "x-pl-description": "input=url: adres feedu (http/https).",
            "type": "string"
          },
          "source": {
            "description": "input=source: a connected shop source id.",
            "x-pl-description": "input=source: identyfikator podłączonego sklepu.",
            "type": "string"
          },
          "refresh_hours": {
            "description": "input=url: download every 0 (never), 1, 3, 6, 12 or 24 hours.",
            "x-pl-description": "input=url: pobieranie co 0 (nigdy), 1, 3, 6, 12 albo 24 godziny.",
            "type": "integer",
            "enum": [
              0,
              1,
              3,
              6,
              12,
              24
            ]
          },
          "parents": {
            "description": "input=feeds or flow: 1–10 feeds with their own products, in priority order.",
            "x-pl-description": "input=feeds albo flow: 1–10 feedów z własnymi produktami, w kolejności ważności.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "graph": {
            "description": "input=flow: a whole canvas (as in PUT /feeds/{id}/flow) instead of parents.",
            "x-pl-description": "input=flow: całe płótno (jak w PUT /feeds/{id}/flow) zamiast parents.",
            "type": "object"
          },
          "output": {
            "description": "Served format: \"\" Google/Meta XML, ceneo, csv, openai (ChatGPT Ads CSV).",
            "x-pl-description": "Format wyjścia: \"\" Google/Meta XML, ceneo, csv, openai (CSV dla ChatGPT Ads).",
            "type": "string",
            "enum": [
              "",
              "ceneo",
              "csv",
              "openai"
            ]
          }
        },
        "required": [
          "name",
          "input"
        ]
      },
      "FeedUpdate": {
        "type": "object",
        "properties": {
          "name": {
            "description": "2–120 characters.",
            "x-pl-description": "2–120 znaków.",
            "type": "string"
          },
          "url": {
            "description": "input=url only.",
            "x-pl-description": "Tylko input=url.",
            "type": "string"
          },
          "refresh_hours": {
            "description": "input=url only.",
            "x-pl-description": "Tylko input=url.",
            "type": "integer",
            "enum": [
              0,
              1,
              3,
              6,
              12,
              24
            ]
          },
          "autofix": {
            "description": "Automatic fixes on or off (feeds with rules).",
            "x-pl-description": "Automatyczne poprawki włączone lub wyłączone (feedy z regułami).",
            "type": "boolean"
          },
          "parents": {
            "description": "input=feeds only.",
            "x-pl-description": "Tylko input=feeds.",
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "output": {
            "description": "Served format (a flow's output block follows).",
            "x-pl-description": "Format wyjścia (bloczek wyjścia przepływu się dostosuje).",
            "type": "string",
            "enum": [
              "",
              "ceneo",
              "csv",
              "openai"
            ]
          },
          "link_tagging": {
            "$ref": "#/components/schemas/LinkTagging"
          }
        }
      },
      "FeedRules": {
        "type": "object",
        "properties": {
          "rules": {
            "description": "Ordered rules: id, name, off, match (\"\"/all/any), when [{field, op, value, to}], then and else [{type, field, value, with, from}]. Replaces all rules. Refused for flows.",
            "x-pl-description": "Reguły w kolejności: id, name, off, match (\"\"/all/any), when [{field, op, value, to}], then i else [{type, field, value, with, from}]. Zastępuje wszystkie reguły. Odrzucane dla przepływów.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "rules"
        ],
        "additionalProperties": false
      },
      "FeedFlow": {
        "type": "object",
        "properties": {
          "graph": {
            "description": "The canvas {nodes: [{id, type, label, config, x, y}], edges: [{from, port, to}]}. Node types: input {feed, processed}, filter and branch {match, when}, change {actions}, autofix, categories, output {format}. Ports: out; branch yes/no. Exactly one output; every node on a path from an input to the output; no loops; each feed once. A refused canvas answers 400 with `node_id`.",
            "x-pl-description": "Płótno {nodes: [{id, type, label, config, x, y}], edges: [{from, port, to}]}. Typy bloczków: input {feed, processed}, filter i branch {match, when}, change {actions}, autofix, categories, output {format}. Wyjścia: out; branch yes/no. Dokładnie jedno wyjście; każdy bloczek na drodze od wejścia do wyjścia; bez pętli; każdy feed raz. Odrzucone płótno zwraca 400 z `node_id`.",
            "type": "object"
          }
        },
        "required": [
          "graph"
        ],
        "additionalProperties": false
      },
      "FeedPreviewRequest": {
        "type": "object",
        "properties": {
          "rules": {
            "description": "Rules to try (feeds with rules).",
            "x-pl-description": "Reguły do sprawdzenia (feedy z regułami).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "graph": {
            "description": "A canvas to try (flows).",
            "x-pl-description": "Płótno do sprawdzenia (przepływy).",
            "type": "object"
          }
        }
      },
      "FeedPreview": {
        "type": "object",
        "properties": {},
        "description": "What the rules or canvas would do to every product, without saving: products, left out, changed, fixes, problems and average score before and after, sample changes; `changed_content` = products changed by more than the notation of a value (price format, spaces); `issue_causes` = for each problem the served products gain, what changed on them (fix code, `category`, `rules`, `manual`) → products; for a flow `nodes` (products in and on per block) and `duplicates`.",
        "x-pl-description": "Co reguły albo płótno zrobiłyby każdemu produktowi, bez zapisu: produkty, pominięte, zmienione, poprawki, problemy i średnia ocena przed i po, przykładowe zmiany; `changed_content` = produkty zmienione bardziej niż w zapisie wartości (format ceny, spacje); `issue_causes` = dla każdego problemu, którego przybywa w feedzie wyjściowym, co zmieniło się w tych produktach (kod poprawki, `category`, `rules`, `manual`) → produkty; dla przepływu `nodes` (produkty na wejściu i dalej na każdym bloku) i `duplicates`."
      },
      "FeedCategories": {
        "type": "object",
        "properties": {},
        "description": "Shop categories of the feed's products (most products first) with the Google category each one gets: `source` person (chosen or confirmed by a person, never changed automatically), auto (chosen by Basketly, with `confidence` 0–100; `review` = below 60, worth a look), broad (an occasion such as \"Promocje\": each product gets a category by its own title, `by_title` counts them) or \"\" (nothing fits); `auto` is Basketly's current choice even where a person chose otherwise; up to three `suggestions`; `summary` counts mapped, person, auto, broad, review and `covered` products, split into `covered_person`, `covered_auto`, `covered_title` (by product title) and `covered_own` (the shop's own valid category), plus `review_products` (products in rows worth a look).",
        "x-pl-description": "Kategorie sklepu z produktów feedu (od najliczniejszych) z kategorią Google, którą dostaje każda: `source` person (wybrana lub zatwierdzona przez człowieka, nigdy nie zmienia się sama), auto (wybrana przez Basketly, z `confidence` 0–100; `review` = poniżej 60, warto sprawdzić), broad (okazja, np. \"Promocje\": każdy produkt dostaje kategorię po własnej nazwie, `by_title` je liczy) albo \"\" (nic nie pasuje); `auto` to bieżący wybór Basketly także tam, gdzie człowiek wybrał inaczej; do trzech podpowiedzi `suggestions`; `summary` liczy przypisane, ludzkie, automatyczne, szerokie, do sprawdzenia i produkty z kategorią (`covered`) z rozbiciem na `covered_person`, `covered_auto`, `covered_title` (po nazwie produktu) i `covered_own` (własna poprawna kategoria sklepu), oraz `review_products` (produkty w wierszach do sprawdzenia)."
      },
      "FeedCategoriesSave": {
        "type": "object",
        "properties": {
          "categories": {
            "description": "[{name, google, own, auto, confidence, broad}] — shop category, Google category number (0 = none), own name (\"\" = keep); without `auto` the Google category is a person's choice and is never changed automatically; with `auto: true` it stays Basketly's to recalculate. Replaces the whole list.",
            "x-pl-description": "[{name, google, own, auto, confidence, broad}] — kategoria sklepu, numer kategorii Google (0 = brak), własna nazwa (\"\" = bez zmian); bez `auto` kategoria Google jest wyborem człowieka i nigdy nie zmienia się sama; z `auto: true` Basketly może ją przeliczyć. Zastępuje całą listę.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "categories"
        ],
        "additionalProperties": false
      },
      "FeedCategoriesChange": {
        "type": "object",
        "properties": {
          "changes": {
            "description": "1–500 rows to change: [{name, google?, confirm?, restore?, own?}] — `name` = shop category as GET gives it; one of `google` (a Google category id: a person's choice, wins from then on), `confirm: true` (the current automatic choice becomes a person's) or `restore: true` (back to Basketly's automatic choice, chosen again), and/or `own` (own name, \"\" removes it). Other rows stay as they are.",
            "x-pl-description": "1–500 wierszy do zmiany: [{name, google?, confirm?, restore?, own?}] — `name` = kategoria sklepu jak w GET; jedno z: `google` (numer kategorii Google: wybór człowieka, od teraz wygrywa), `confirm: true` (bieżący wybór automatyczny staje się wyborem człowieka) albo `restore: true` (powrót do automatycznego wyboru Basketly, wybranego od nowa), i/lub `own` (własna nazwa, \"\" usuwa). Pozostałe wiersze zostają bez zmian.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "required": [
          "changes"
        ],
        "additionalProperties": false
      },
      "GoogleCategories": {
        "type": "object",
        "properties": {},
        "description": "Up to 30 categories of Google's taxonomy matching the words (Polish or English) or the id, best first: id, path in the request's language, alt = path in the other language.",
        "x-pl-description": "Do 30 kategorii taksonomii Google pasujących do słów (po polsku albo angielsku) albo numeru, od najlepszej: id, ścieżka w języku zapytania, alt = ścieżka w drugim języku."
      },
      "GoogleTaxonomy": {
        "type": "object",
        "properties": {},
        "description": "The version of Google's product taxonomy in use: version (Google's date), categories, source embedded (the copy in Basketly) | downloaded, fetched and checked (unix seconds, 0 = never), error (the last check failed; the version in use stays), job ({number, status} of this organisation's waiting check, or null).",
        "x-pl-description": "Wersja taksonomii produktów Google w użyciu: version (data Google), categories, source embedded (kopia w Basketly) | downloaded, fetched i checked (sekundy unix, 0 = nigdy), error (ostatnie sprawdzenie nie powiodło się; wersja w użyciu zostaje), job ({number, status} czekającego sprawdzenia tej organizacji albo null)."
      },
      "GettingStarted": {
        "type": "object",
        "properties": {},
        "description": "The setup checklist („Pierwsze kroki”), read from the organisation's own records: `steps` (id shop | meta | flow | feed | ads | platforms, done, optional — only platforms, count — sources, receivers, running flows, feeds, ad accounts read, connected platforms, orders — orders read, for shop, link — the panel address where the step is done), `done` and `required` (required steps) and `left` (required steps still to do).",
        "x-pl-description": "Lista pierwszych kroków („Pierwsze kroki”) liczona z danych organizacji: `steps` (id shop | meta | flow | feed | ads | platforms, done, optional — tylko platforms, count — źródła, odbiorcy, działające przepływy, feedy, odczytane konta reklamowe, połączone platformy, orders — odczytane zamówienia przy shop, link — adres w panelu, w którym krok się wykonuje), `done` i `required` (kroki wymagane) oraz `left` (wymagane kroki do zrobienia)."
      },
      "SetupMap": {
        "type": "object",
        "properties": {},
        "description": "The connection map: `nodes` (id, kind source|account|feed|feed_output|integration|orders|products|conversions|segments|audience|automations|templates|target|api|agents, column in | hub | out, label, detail, status ok | warn | error | off, reason, link — the panel address that manages it, counts, items — e.g. the flows of a receiver or the active automations with their trigger) and `edges` (id, from, to, kind, status, label, reason). Sections the member may not see are left out; no secrets.",
        "x-pl-description": "Mapa połączeń: `nodes` (id, kind source|account|feed|feed_output|integration|orders|products|conversions|segments|audience|automations|templates|target|api|agents, column in | hub | out, etykieta, opis, status ok | warn | error | off, powód, link — adres w panelu, w którym się tym zarządza, liczby, items — np. przepływy odbiorcy albo włączone automatyzacje z wyzwalaczem) i `edges` (id, from, to, kind, status, etykieta, powód). Sekcje, których członek nie widzi, są pominięte; bez sekretów."
      },
      "Integrations": {
        "type": "object",
        "properties": {},
        "description": "The Integracje page: categories, the catalogue (key, category, mode, state connected | error | off | planned | unavailable — unavailable: the server cannot start the sign-in it needs yet and nothing is connected —, count, where it is managed) and the connections (kind ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, name, public settings — for ad platforms login, account, currency, conversion —, status ok | error | unverified | setup, error, checked_at, send_conversions, can_send, account_id and account_name — the ad account the connection reads or sends to and the name the platform gives it, empty until read —, archived and archived_at — disconnected in the panel („Odłącz”): it sends and reads nothing and counts as not connected, while its send history and the spend it read stay in the reports; the panel restores it or deletes it for good —, display_name); an unavailable ad platform lists its `missing` server settings only to platform admins; the `smsportal` entry (phones connected through smsportal.app; other SMS providers are the `sms` entry) carries `one_click` — true when the server connects a phone with one click, false when only a pasted smsportal API key works. Keys and sign-in grants are never returned.",
        "x-pl-description": "Strona Integracje: kategorie, katalog (klucz, kategoria, sposób, stan connected | error | off | planned | unavailable — unavailable: serwer nie może jeszcze uruchomić potrzebnego logowania i nic nie jest połączone —, liczba, gdzie się nim zarządza) i połączenia (rodzaj ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, nazwa, ustawienia jawne — dla platform reklamowych login, konto, waluta, konwersja —, status ok | error | unverified | setup, błąd, checked_at, send_conversions, can_send, account_id i account_name — konto reklamowe, które połączenie czyta albo do którego wysyła, i nazwa nadana mu przez platformę, pusta przed odczytem —, archived i archived_at — odłączone w panelu („Odłącz”): niczego nie wysyła ani nie czyta i nie liczy się jako połączone, a historia wysyłek i pobrane wydatki zostają w raportach; panel je przywraca albo usuwa na stałe —, display_name); niedostępna platforma reklamowa wymienia brakujące ustawienia serwera `missing` tylko administratorom platformy; pozycja `smsportal` (telefony połączone przez smsportal.app; pozostali dostawcy SMS to pozycja `sms`) ma `one_click` — true, gdy serwer łączy telefon jednym kliknięciem, false, gdy działa tylko wklejony klucz API smsportal. Klucze i zgody logowania nigdy nie są zwracane."
      },
      "OrderList": {
        "type": "object",
        "properties": {
          "orders": {
            "description": "Orders: id, number, placed_at, status, status_type (new, open, closed, cancelled), paid, bought, cancelled, currency, total, shipping, items, city, buyer {id, name}, source_name, source_kind (shoper, idosell, baselinker, woocommerce, shopify…), lines (line count), first_product {name, variant, content_id, quantity, product (record id or empty), image}, sends ([{destination meta | ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, status accepted | failed | waiting | skipped}] — the worst outcome per destination), ad_source. `ad_source` = Basketly's own last-click reading of where the order came from, never a platform's attribution: platform (meta | google_ads | microsoft_ads | tiktok | pinterest | openai_ads | email | comparison | other | direct | unknown), method (click_id | utm | ids | feed | referrer | none), link (server = tracking_id in the order, browser = thank-you page linkOrder, shop = the shop's landing data, none), deduced, campaign / adset / ad {id, name}, resolved (ids | names | empty), utm {source, medium, campaign, content, term, id}, click_at, clicks (click ids of the visit: fbc, gclid, gbraid, wbraid, msclkid, ttclid, ttp, epik, oppref, obref), referrer (host), landing (path), first_touch, feed {id, name, channel, product} (the served feed and catalogue product of the tagged link the visit landed on).",
            "x-pl-description": "Zamówienia: id, number, placed_at, status, status_type (new, open, closed, cancelled), paid, bought, cancelled, currency, total, shipping, items, city, buyer {id, name}, source_name, source_kind (shoper, idosell, baselinker, woocommerce, shopify…), lines (liczba pozycji), first_product {name, variant, content_id, quantity, product (id rekordu albo puste), image}, sends ([{destination meta | ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, status accepted | failed | waiting | skipped}] — najgorszy wynik na miejsce docelowe), ad_source. `ad_source` = odczytanie Basketly (ostatnie kliknięcie reklamy w wizytach kupującego), nigdy atrybucja platformy: platform (meta | google_ads | microsoft_ads | tiktok | pinterest | openai_ads | email | comparison | other | direct | unknown), method (click_id | utm | ids | feed | referrer | none), link (server = tracking_id w zamówieniu, browser = linkOrder na stronie podziękowania, shop = dane sklepu o wejściu, none), deduced, campaign / adset / ad {id, name}, resolved (ids | names | empty), utm {source, medium, campaign, content, term, id}, click_at, clicks (identyfikatory kliknięć z wizyty: fbc, gclid, gbraid, wbraid, msclkid, ttclid, ttp, epik, oppref, obref), referrer (host), landing (ścieżka), first_touch, feed {id, name, channel, product} (feed i produkt katalogu z otagowanego linku, z którego przyszła wizyta).",
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "ad_facets": {
            "description": "Orders of the selection (before the platform / campaign filters) per ad platform (`platforms`: platform, orders) and per campaign (`campaigns`: platform, key, name, orders; at most 100).",
            "x-pl-description": "Zamówienia wyboru (przed filtrami platformy / kampanii) na platformę reklamy (`platforms`: platform, orders) i na kampanię (`campaigns`: platform, key, name, orders; najwyżej 100).",
            "type": "object"
          },
          "facets": {
            "description": "The period's orders (all states, before the other filters) per shop (`sources`: id, name, kind, orders), shop status (`shop_statuses`: status, status_type, orders) and delivery country (`countries`: country, orders); at most 100 each.",
            "x-pl-description": "Zamówienia okresu (wszystkie stany, przed pozostałymi filtrami) na sklep (`sources`: id, name, kind, orders), status sklepu (`shop_statuses`: status, status_type, orders) i kraj dostawy (`countries`: country, orders); najwyżej 100 każdego.",
            "type": "object"
          },
          "page_size": {
            "description": "Orders per page (per_page).",
            "x-pl-description": "Zamówień na stronę (per_page).",
            "type": "integer"
          },
          "total": {
            "description": "All matching orders.",
            "x-pl-description": "Wszystkie pasujące zamówienia.",
            "type": "integer"
          },
          "summary": {
            "description": "Bought orders, unpaid, cancelled, items, revenue per currency, average basket, buyers, new and returning buyers.",
            "x-pl-description": "Kupione zamówienia, nieopłacone, anulowane, sztuki, przychód na walutę, średni koszyk, kupujący, nowi i powracający.",
            "type": "object"
          }
        },
        "description": "A page of the Zamówienia list (50 orders by default, newest first unless `sort` says otherwise) with a summary of the whole selection.",
        "x-pl-description": "Strona listy Zamówienia (domyślnie 50 zamówień, od najnowszych, chyba że `sort` mówi inaczej) z podsumowaniem całego wyboru."
      },
      "Order": {
        "type": "object",
        "properties": {},
        "description": "One order with its lines (name, variant, code, EAN, content_id, quantity, unit price, value, matched product record), its buyer's totals, `ad_source` (as on the list) and `sends`: each destination of the purchase (destination meta | ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, name, event_name, status, error) with the `identifiers` its payload carried (names only, e.g. fbc, gclid, ttclid, click_id, em).",
        "x-pl-description": "Jedno zamówienie z pozycjami (nazwa, wariant, kod, EAN, content_id, ilość, cena, wartość, dopasowany produkt), sumami kupującego, `ad_source` (jak na liście) i `sends`: każde miejsce, do którego poszedł zakup (destination meta | ga4 | tiktok | pinterest | klaviyo | openai_ads | google_ads | microsoft_ads, name, event_name, status, error) z identyfikatorami w treści (`identifiers`, tylko nazwy, np. fbc, gclid, ttclid, click_id, em)."
      },
      "TemplateList": {
        "type": "object",
        "properties": {
          "templates": {
            "description": "Templates: id, name, format, updated.",
            "x-pl-description": "Szablony: id, name, format, updated.",
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        },
        "description": "Image templates of the organisation.",
        "x-pl-description": "Szablony grafik organizacji."
      },
      "Template": {
        "type": "object",
        "properties": {},
        "description": "One image template with its design (layers).",
        "x-pl-description": "Jeden szablon grafiki z projektem (warstwami)."
      },
      "Guidelines": {
        "type": "object",
        "properties": {},
        "description": "The guideline base: every rule of Google Merchant Center, the Meta catalogue, TikTok and Pinterest that Basketly follows, each with `platform`, `topic`, `severity` (error, warning, tip), `text` (Polish) and `text_en`, the vendor page (`source`, `source_name`), the day a person last checked it (`checked`), `review_since` (unix time the vendor page changed without a review yet, 0 = no; a changed page means it is being reread, not that the rule changed), the product `checks` that enforce it and how many active products break it now (`products`, `by_check`). Also `sources`, `platforms`, `topics`, `products` (active products counted) and `ai_titles` (title suggestions available).",
        "x-pl-description": "Baza wytycznych: każda zasada Google Merchant Center, katalogu Mety, TikToka i Pinteresta, której pilnuje Basketly, z `platform`, `topic`, `severity` (error, warning, tip), `text` (po polsku) i `text_en`, stroną dostawcy (`source`, `source_name`), dniem ostatniego sprawdzenia przez człowieka (`checked`), `review_since` (czas unix, od kiedy strona dostawcy zmieniła się bez przejrzenia, 0 = nie; zmieniona strona znaczy, że jest czytana ponownie, nie że zasada się zmieniła), sprawdzeniami produktów, które jej pilnują (`checks`), i liczbą aktywnych produktów, które ją dziś łamią (`products`, `by_check`). Do tego `sources`, `platforms`, `topics`, `products` (liczone aktywne produkty) i `ai_titles` (czy sugestie tytułów są dostępne)."
      },
      "TitleSuggestions": {
        "type": "object",
        "properties": {},
        "description": "1–3 proposed titles (`suggestions`: `title`, `guidelines` — ids of the title rules it follows, `checks` — Basketly's tips the title still has), the `current` title the feeds serve, the title `guidelines` sent to the model with their sources, and the `model`. Nothing is saved; apply one with PUT /products/{product}/overrides.",
        "x-pl-description": "1–3 proponowane tytuły (`suggestions`: `title`, `guidelines` — identyfikatory zasad tytułu, których się trzyma, `checks` — wskazówki Basketly, które tytuł wciąż ma), bieżący tytuł z feedów (`current`), zasady tytułów wysłane do modelu ze źródłami (`guidelines`) i `model`. Nic nie jest zapisywane; zastosuj propozycję przez PUT /products/{product}/overrides."
      }
    }
  }
}
