LuckyFit API ## Sections • [LuckyFit Public Integration API](https://app.theneo.io/luckysoft/luckyfit-api/luckyfit-public-integration-api.md): LuckyFit public integration API. All endpoints are mounted under the /api prefix and require organization network-key authentication ( Api-Key header). The key identifies the "network" (root organization) and may optionally restrict access to specific branches. Without a valid key the API returns 401 Unauthorized with a body of { "success": false, "session_expired": true, ... } . Response format Endpoints do not use HTTP status codes for business logic: on a validation error they typically return 200 OK with success: false and a message in error . There are two envelopes: data envelope ( send_data_response ): { success, data, error, total } . crud envelope ( send_crud_response ): { success, data, error, error_code, total, summary } . The /terminal/* endpoints are the exception: they implement the external payment terminal protocol as-is, return a bare JSON body without any envelope, and do use HTTP status codes — 200 on success, 401 { "result": "userNotIdentified" } when the key is missing or invalid, and 403 { "result": "<code>", "description": "<text>" } on a business error. Branch resolution (organization_id) For create/update operations, if organization_id is omitted the branch is resolved automatically: if the Api-Key is restricted to exactly one branch, that branch is used; if the network has exactly one branch, that branch is used; otherwise an explicit organization_id is required. Pagination List ( GET ) endpoints accept start / limit query parameters and return a total in the response envelope: start — 1-based index of the first record to return, i.e. offset = start - 1 . Defaults to 1 . limit — page size. Defaults to 25 ; values above 100 are silently capped to 100 . total — the total number of records matching the request's filters, across all pages (not just the current page's data length). Exception: GET /classes/schedule already uses start / finish for the schedule period, so pagination there uses page_start / page_limit instead (same semantics and defaults). Rate limiting All API requests are limited to 5 requests per second per Api-Key (across every endpoint, including /terminal/* ). Requests above that rate are rejected — the client should retry them after a short pause. Practical consequences for integrations: Do not fan out parallel requests; a single sequential client stays within the limit. For bulk reads use the largest allowed page ( limit=100 ) instead of many small pages, and pace the paging loop. Cache rarely-changing dictionaries ( /info_sources , /organizations , /memberships ) instead of re-fetching them per operation. • [Leads](https://app.theneo.io/luckysoft/luckyfit-api/leads.md): CRM leads / inquiries • [Create a lead (inquiry)](https://app.theneo.io/luckysoft/luckyfit-api/leads/create-a-lead-inquiry.md): Creates a new lead. The `name` field is required. The branch is resolved from `organization_id` or automatically (see the API description). • [Info sources](https://app.theneo.io/luckysoft/luckyfit-api/info-sources.md): Information sources • [List information sources](https://app.theneo.io/luckysoft/luckyfit-api/info-sources/list-information-sources.md) • [Memberships](https://app.theneo.io/luckysoft/luckyfit-api/memberships.md): Membership catalog (assortment) • [Membership catalog (assortment available for sale)](https://app.theneo.io/luckysoft/luckyfit-api/memberships/membership-catalog-assortment-available-for-sale.md): Returns the network's memberships available for sale. Supports filtering by sale/access branch, kind, subscription flag, and segment. With `detalization=true`, each membership also includes a `detalization` object with addons, step payments, and service payments, plus `total_price` — the first payment amount assuming the membership starts today (body schedule due today + service payments without a shift). • [List access segments](https://app.theneo.io/luckysoft/luckyfit-api/memberships/list-access-segments.md) • [Addons](https://app.theneo.io/luckysoft/luckyfit-api/addons.md): Membership addons (available catalog and client purchases) • [Addons available for a membership](https://app.theneo.io/luckysoft/luckyfit-api/addons/addons-available-for-a-membership.md): Returns the addons offered for the given catalog membership (assortment plan), each with its price and a list of conditions (the addon's composition). • [Addons purchased on a client's membership](https://app.theneo.io/luckysoft/luckyfit-api/addons/addons-purchased-on-a-client-s-membership.md) • [Purchase an addon for a client's membership](https://app.theneo.io/luckysoft/luckyfit-api/addons/purchase-an-addon-for-a-client-s-membership.md): Registers an addon purchase for the client's membership. `addon_id` is required and must be one of the addons offered for the membership's plan. If `price` is omitted, the plan's addon price is used. • [Clients](https://app.theneo.io/luckysoft/luckyfit-api/clients.md): Clients • [Search clients](https://app.theneo.io/luckysoft/luckyfit-api/clients/search-clients.md): Returns clients of the network, sorted by `id` descending. Paginated — see `start`/`limit` and the `total` response field. All filters are optional and combined with AND. `surname`/`name` match by prefix, `phone` is a partial match. • [Create a client](https://app.theneo.io/luckysoft/luckyfit-api/clients/create-a-client.md): `surname`, `name`, and `sex` are required. • [Update a client](https://app.theneo.io/luckysoft/luckyfit-api/clients/update-a-client.md) • [Delete a client](https://app.theneo.io/luckysoft/luckyfit-api/clients/delete-a-client.md) • [Client memberships](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships.md): Memberships of a specific client • [Client's memberships](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/client-s-memberships.md) • [Sell a membership to a client](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/sell-a-membership-to-a-client.md): `membership_id` (a catalog membership ID) is required. • [Get a client's membership](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/get-a-client-s-membership.md): Returns properties of a single issued membership for the client. • [Create a client and sell a membership](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/create-a-client-and-sell-a-membership.md): Creates a new client and sells a membership in a single atomic operation. If any step fails (client validation, membership sale, etc.), the entire operation is rolled back and nothing is persisted. Client fields can be sent at the top level or nested inside a `client` object (same as `POST /clients`). `surname`, `name`, and `sex` are required. Branch (`organization_id`) can be taken from the client block or from `sale_organization_id`. • [Validate a promocode / promo-action code](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/validate-a-promocode-promo-action-code.md): Checks whether `code` is a currently valid promocode or promo-action code for the given client and membership plan. The lookup applies the same rules used when selling a membership: - the code must be active (current time within the action's `start`/`finish` window); - per-client / one-time codes (`code_kind = 1`) are rejected if the client has already used them; - if the action restricts to membership segments, the plan (`ticket_id`) must match one of those segments; - codes tied to goods (`goods` set) are not valid for memberships. On success the `data` field holds the matching promo-action (with the resolved `code`); when the code is invalid `data` is `null` while `success` stays `true`. The returned `promoaction_id` / `code` can then be passed to `POST /clients/{client_id}/memberships`. • [Pay off membership debt](https://app.theneo.io/luckysoft/luckyfit-api/client-memberships/pay-off-membership-debt.md): If there is outstanding debt, redirects (302) to the payment page. If there is no debt or no account, returns `200` with `{ success: false, error }`. • [Organizations](https://app.theneo.io/luckysoft/luckyfit-api/organizations.md): Network organizations / branches • [List network branches](https://app.theneo.io/luckysoft/luckyfit-api/organizations/list-network-branches.md): Returns the child organizations (branches) of the current network. • [Classes](https://app.theneo.io/luckysoft/luckyfit-api/classes.md): Group class schedule • [Group class schedule grid](https://app.theneo.io/luckysoft/luckyfit-api/classes/group-class-schedule-grid.md): Returns scheduled group classes for the network (or a selected branch) in the given period. • [Terminal](https://app.theneo.io/luckysoft/luckyfit-api/terminal.md): Self-service payment terminal for paying off client debts. Unlike the rest of the API these endpoints follow the external terminal protocol verbatim: camelCase fields, a bare JSON body without the `success`/`data`/`error` envelope, and meaningful HTTP status codes (200 / 401 / 403). • [Health check of the terminal integration](https://app.theneo.io/luckysoft/luckyfit-api/terminal/health-check-of-the-terminal-integration.md): Returns `{"result":"ok"}` when the service is reachable and the `Api-Key` is valid. Used by the payment terminal on start-up. • [Identify a client and return the list of debts to pay](https://app.theneo.io/luckysoft/luckyfit-api/terminal/identify-a-client-and-return-the-list-of-debts-to-pay.md): Step 1 of the self-service payment terminal flow. The client authenticates on the terminal with a MiFare card or a QR code from the mobile app; customerId carries whatever the reader produced. Lookup cascade for customerId : mobile app QR / barcode ( ID:<id> or <id>|<ts>|<guest> ); exact match on the card code fitness_clients.tag ; fitness_clients.access_pin ; single-use mobile app PIN ( fitness_client_pins , TTL 2 minutes). The returned invoiceData contains only positions with a debt greater than zero: invoiceType Source invoiceId membership membership debt ( fitness_client_tickets ) account_summ_id personal personal training / object reserve ( fitness_reserves ) fitness_orders.account_id group group class booking ( fitness_lesson_calendar_bookings ) fitness_orders.account_id invoice any other unpaid bill ( fitness_orders ) fitness_orders.account_id Membership fee debt and a negative deposit balance are intentionally not exposed. • [Register a payment made on the terminal](https://app.theneo.io/luckysoft/luckyfit-api/terminal/register-a-payment-made-on-the-terminal.md): Step 2 of the self-service payment terminal flow. Each element of `paymentData` creates a posted (`signed = true`) transaction against the account addressed by `invoiceId`: - `paymentType: cash` -> `paykind_id = 2` (cash), `bankCard` -> `paykind_id = 3` (credit card); - `finoperation_id` is derived from the account kind: `2` for a membership, `4` for a bill; - `firm_id` is taken from `merchantId` when present; - the transaction organization is the club addressed by `gymId`, i.e. the club the terminal stands in; - `payed_at` on a fully paid bill is set automatically. All positions of a request are written in a single database transaction: either everything is registered or nothing is. **Idempotency.** Every transaction is stamped with `notes = "TERMINAL# "`. If a payment with the same `transactionId` already exists for the client, the endpoint answers `{"result":"ok"}` without creating anything — safe to retry after a network failure. Fiscalisation is not performed on the LuckyFit side: the receipt is printed by the terminal itself. • [Accounting](https://app.theneo.io/luckysoft/luckyfit-api/accounting.md): Transaction export for accounting systems • [Export transactions for a period](https://app.theneo.io/luckysoft/luckyfit-api/accounting/export-transactions-for-a-period.md): Returns signed (`signed = 1`) transactions for the `[lodate, hidate]` period, with line-item details for membership payments, membership fees, and invoices.