Dla deweloperów

API SilkCRM

Połącz sklep internetowy salonu (Shopify, WooCommerce albo własny) z SilkCRM: pokaż w sklepie ofertę salonu, wydawaj vouchery i karnety sprzedane online, a o zdarzeniach w salonie dowiaduj się z webhooków.

Adres bazowy
https://app.silkcrm.net/api/rest/v1
Uwierzytelnianie
Authorization: Bearer silk_live_…
Format
JSON, kwoty w groszach, czasy w ISO 8601
Wersja
v1 · 1.0.0 · OpenAPI 3.1 (JSON)

Szybki start

Pierwsze zapytanie w pięć minut

REST API SilkCRM dla sklepów internetowych salonów: odczyt oferty salonu oraz wydawanie voucherów kwotowych i karnetów sprzedanych w sklepie.

  1. Sprawdź plan salonu. Dostęp przez API mają plany Pro i wyższe. Inny plan dostaje 403 feature_not_available_on_plan.
  2. Wygeneruj klucz API. W aplikacji wejdź w Ustawienia → Zaawansowane → Klucze API. W karcie „Nowy klucz” wpisz nazwę (np. „Sklep Shopify”), w „Poziom uprawnień” zostaw „Tylko odczyt”, w „Dodatkowe uprawnienia” zaznacz „Sklep internetowy (vouchery i karnety ze sklepu)” i kliknij „Utwórz klucz”. Taki klucz ma zakresy read:* i write:commerce. Pełny klucz zobaczysz tylko raz.
  3. Trzymaj klucz po stronie serwera. Zapisz go w zmiennej środowiskowej SILK_API_KEY serwera sklepu. Nigdy nie wstawiaj go do kodu wykonywanego w przeglądarce klientki: kto zna klucz, wydaje vouchery w imieniu salonu.
  4. Wyślij pierwsze zapytanie i sprawdź, które salony widzi klucz:
Salony konta
curl "https://app.silkcrm.net/api/rest/v1/locations" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "data": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000001",
      "name": "Salon Alicja - Centrum",
      "address": "ul. Marszałkowska 10",
      "city": "Warszawa",
      "phone": "+48221234567",
      "timezone": "Europe/Warsaw",
      "accepts_online_bookings": true
    },
    {
      "id": "8f1c0000-0000-4000-8000-000000000002",
      "name": "Salon Alicja - Mokotów",
      "address": "ul. Puławska 120",
      "city": "Warszawa",
      "phone": "+48221234567",
      "timezone": "Europe/Warsaw",
      "accepts_online_bookings": false
    }
  ],
  "next_cursor": null
}

Uwierzytelnianie

Każde zapytanie niesie klucz API salonu w nagłówku Authorization: Bearer silk_live_…. Inne sposoby logowania (np. OAuth) dostają 403 api_key_required. Odczyty wymagają zakresu read:*, zapisy - zakresu write:commerce (nie wynika z write:all). Plan salonu musi obejmować dostęp przez API (inaczej 403 feature_not_available_on_plan).

Dokument OpenAPI 3.1 pobierzesz bez klucza: https://app.silkcrm.net/api/rest/v1/openapi.json. Zaimportuj go do Postmana, Insomnii albo generatora klienta.

Przypadki użycia

Typowe scenariusze sklepu

Każdy przykład pochodzi z prawdziwego przebiegu na koncie testowym. Wybór języka (curl, JavaScript, PHP dla WordPressa i WooCommerce) obowiązuje na całej stronie.

Voucher kupiony w sklepie

Klientka płaci w sklepie za voucher kwotowy. Sklep po opłaceniu zamówienia zakłada (albo odnajduje) jej kartę w Silku i wydaje voucher. Silk nic klientce nie wysyła, wiadomość z kodem zostaje po stronie sklepu.

  1. Znajdź albo załóż kartę klientki po telefonie lub e-mailu z zamówienia. Zgody marketingowe przekazujesz tylko wtedy, gdy klientka je w sklepie zaznaczyła. POST /clients/resolve

    Nowa klientka z telefonem, e-mailem i zgodą SMS
    curl -X POST "https://app.silkcrm.net/api/rest/v1/clients/resolve" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-client' \
      -d '{
      "external_order_id": "#1043",
      "shop": "shopify",
      "client": {
        "phone": "500 100 200",
        "email": "anna.nowak@example.com",
        "first_name": "Anna",
        "last_name": "Nowak",
        "consents": {
          "sms": {
            "granted": true,
            "granted_at": "2026-11-03T10:00:00.000Z"
          }
        }
      }
    }'
    OdpowiedźJSON
    HTTP 200
    
    {
      "dry_run": false,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "created": true
    }
  2. Wydaj voucher na zwrócone client_id. amount_cents to wartość vouchera, paid_cents to kwota zapłacona w sklepie (mniejsza przy rabacie). POST /vouchers

    Voucher 200 zł sprzedany z rabatem za 180 zł
    curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-voucher' \
      -d '{
      "external_order_id": "#1043",
      "external_order_line_id": "1",
      "shop": "shopify",
      "amount_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "gift_message": "Wszystkiego najlepszego!"
    }'
    OdpowiedźJSON
    HTTP 201
    
    {
      "id": "8f1c0000-0000-4000-8000-000000000008",
      "status": "active",
      "amount_cents": 20000,
      "balance_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "recipient_phone": null,
      "purchaser_client_id": null,
      "gift_message": "Wszystkiego najlepszego!",
      "expires_at": null,
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z",
      "dry_run": false
    }
  3. Przy zwrocie zamówienia unieważnij voucher. Działa wyłącznie dla vouchera utworzonego przez API dla tego samego zamówienia i tylko, dopóki nie został użyty. POST /vouchers/{id}/void

    Zwrot vouchera w sklepie
    curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers/8f1c0000-0000-4000-8000-000000000008/void" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-refund-voucher' \
      -d '{
      "external_order_id": "#1043",
      "shop": "shopify",
      "reason": "Klientka zwróciła zamówienie"
    }'
    OdpowiedźJSON
    HTTP 200
    
    {
      "id": "8f1c0000-0000-4000-8000-000000000008",
      "status": "void",
      "amount_cents": 20000,
      "balance_cents": 0,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "recipient_phone": null,
      "purchaser_client_id": null,
      "gift_message": "Wszystkiego najlepszego!",
      "expires_at": null,
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z",
      "dry_run": false
    }

Karnet kupiony w sklepie

Sklep sprzedaje karnet z szablonu, który salon oznaczył jako sprzedawany poza kasą. Szablony promocyjne nie są sprzedawane przez API.

  1. Pobierz szablony karnetów i pokaż w sklepie te, które można sprzedać. GET /pass-templates

    Szablony karnetów
    curl "https://app.silkcrm.net/api/rest/v1/pass-templates" \
      -H "Authorization: Bearer $SILK_API_KEY"
    OdpowiedźJSON
    HTTP 200
    
    {
      "data": [
        {
          "id": "8f1c0000-0000-4000-8000-000000000006",
          "name": "Karnet 5 manicure",
          "description": "Pięć wizyt manicure hybrydowego.",
          "uses_total": 5,
          "price_cents": 50000,
          "validity_days": 365,
          "service_ids": [
            "8f1c0000-0000-4000-8000-000000000003"
          ],
          "sellable": true
        }
      ],
      "next_cursor": null
    }
  2. Po opłaceniu zamówienia wydaj karnet z szablonu na kartę klientki. POST /passes

    Karnet z szablonu sprzedawanego poza kasą, z rabatem
    curl -X POST "https://app.silkcrm.net/api/rest/v1/passes" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-pass' \
      -d '{
      "external_order_id": "#1043",
      "external_order_line_id": "3",
      "shop": "shopify",
      "template_id": "8f1c0000-0000-4000-8000-000000000006",
      "paid_cents": 45000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007"
    }'
    OdpowiedźJSON
    HTTP 201
    
    {
      "id": "8f1c0000-0000-4000-8000-000000000009",
      "status": "active",
      "template_id": "8f1c0000-0000-4000-8000-000000000006",
      "name": "Karnet 5 manicure",
      "uses_total": 5,
      "uses_left": 5,
      "paid_cents": 45000,
      "unit_value_cents": 9000,
      "service_ids": [
        "8f1c0000-0000-4000-8000-000000000003"
      ],
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "expires_at": "2027-11-03T10:15:00.000Z",
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z",
      "dry_run": false
    }

Ponowione powiadomienie sklepu

Shopify i WooCommerce potrafią wysłać to samo powiadomienie o zamówieniu kilka razy. Wysyłaj każdy zapis z Idempotency-Key zbudowanym z numeru zamówienia i pozycji: ponowienie dostaje tę samą odpowiedź z nagłówkiem Idempotent-Replay: true, a drugi voucher nie powstaje.

  1. To samo żądanie wysłane drugi raz z tym samym kluczem idempotencji:

    Ponowienie z tym samym Idempotency-Key - ta sama odpowiedź, bez drugiego vouchera
    curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-voucher' \
      -d '{
      "external_order_id": "#1043",
      "external_order_line_id": "1",
      "shop": "shopify",
      "amount_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "gift_message": "Wszystkiego najlepszego!"
    }'
    OdpowiedźJSON
    HTTP 201
    Idempotent-Replay: true
    
    {
      "id": "8f1c0000-0000-4000-8000-000000000008",
      "status": "active",
      "amount_cents": 20000,
      "balance_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "recipient_phone": null,
      "purchaser_client_id": null,
      "gift_message": "Wszystkiego najlepszego!",
      "expires_at": null,
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z",
      "dry_run": false
    }

Testy bez skutków (dry-run)

Nagłówek Silk-Dry-Run: 1 wykonuje zapis w całości, łącznie z walidacją i regułami salonu, po czym go wycofuje. Tak sprawdzisz integrację na prawdziwym koncie, zanim sklep zacznie wydawać vouchery naprawdę.

  1. Próba wydania vouchera: odpowiedź ma dry_run: true i id: null.

    Próba (Silk-Dry-Run: 1) - nic nie zostaje zapisane, id = null
    curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-voucher' \
      -H 'Silk-Dry-Run: 1' \
      -d '{
      "external_order_id": "#1043",
      "external_order_line_id": "1",
      "shop": "shopify",
      "amount_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "gift_message": "Wszystkiego najlepszego!"
    }'
    OdpowiedźJSON
    HTTP 201
    Silk-Dry-Run: 1
    
    {
      "id": null,
      "status": "active",
      "amount_cents": 20000,
      "balance_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "recipient_phone": null,
      "purchaser_client_id": null,
      "gift_message": "Wszystkiego najlepszego!",
      "expires_at": null,
      "external_order_id": "#1043",
      "created_at": null,
      "dry_run": true
    }
  2. Reguły salonu obowiązują także w próbie: kwota poza zakresem daje ten sam 422 z nagłówkiem Silk-Dry-Run: 1 i bez niego. Poniżej ten błąd na zwykłym zapisie:

    Kwota poza zakresem ustawionym przez salon
    curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers" \
      -H "Authorization: Bearer $SILK_API_KEY" \
      -H 'Content-Type: application/json' \
      -H 'Idempotency-Key: order-1043-voucher-2' \
      -d '{
      "external_order_id": "#1043",
      "external_order_line_id": "2",
      "shop": "shopify",
      "amount_cents": 100000,
      "paid_cents": 100000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "gift_message": "Wszystkiego najlepszego!"
    }'
    OdpowiedźJSON
    HTTP 422
    
    {
      "error": {
        "code": "voucher_amount_out_of_range",
        "message": "Kwota vouchera jest poza zakresem ustawionym przez salon.",
        "details": {
          "min_cents": 5000,
          "max_cents": 50000
        },
        "request_id": "req-8f1c0001"
      }
    }

Sprawdzenie stanu zamówienia

Jedno zapytanie zwraca wszystko, co Silk utworzył dla zamówienia sklepu: vouchery i karnety z ich bieżącym stanem. Przydaje się do uzgodnień i do panelu obsługi sklepu. Znak # w numerze zamówienia koduj jako %23.

  1. Stan zamówienia #1043: GET /orders/{external_order_id}

    Wszystko, co Silk utworzył dla zamówienia #1043 (# zakodowany jako %23)
    curl "https://app.silkcrm.net/api/rest/v1/orders/%231043" \
      -H "Authorization: Bearer $SILK_API_KEY"
    OdpowiedźJSON
    HTTP 200
    
    {
      "external_order_id": "#1043",
      "shop": "shopify",
      "vouchers": [
        {
          "id": "8f1c0000-0000-4000-8000-000000000008",
          "status": "active",
          "amount_cents": 20000,
          "balance_cents": 20000,
          "paid_cents": 18000,
          "client_id": "8f1c0000-0000-4000-8000-000000000007",
          "recipient_phone": null,
          "purchaser_client_id": null,
          "gift_message": "Wszystkiego najlepszego!",
          "expires_at": null,
          "external_order_id": "#1043",
          "created_at": "2026-11-03T10:15:00.000Z"
        }
      ],
      "passes": [
        {
          "id": "8f1c0000-0000-4000-8000-000000000009",
          "status": "active",
          "template_id": "8f1c0000-0000-4000-8000-000000000006",
          "name": "Karnet 5 manicure",
          "uses_total": 5,
          "uses_left": 5,
          "paid_cents": 45000,
          "unit_value_cents": 9000,
          "service_ids": [
            "8f1c0000-0000-4000-8000-000000000003"
          ],
          "client_id": "8f1c0000-0000-4000-8000-000000000007",
          "expires_at": "2027-11-03T10:15:00.000Z",
          "external_order_id": "#1043",
          "created_at": "2026-11-03T10:15:00.000Z"
        }
      ]
    }

Wizyta z zadatkiem opłaconym w sklepieWkrótce - od 11 listopada 2026

Rezerwacja wizyty z zadatkiem pobranym przez sklep. Zakres i szczegóły opublikujemy razem z udostępnieniem funkcji.

Referencja

Referencja REST API v1

Wszystkie operacje z dokumentu OpenAPI, w kolejności: Katalog, Klientki, Vouchery, Karnety, Zamówienia. Adres każdej operacji to https://app.silkcrm.net/api/rest/v1 + ścieżka.

Katalog

Oferta salonu do pokazania w sklepie: salony, usługi, specjalistki, szablony karnetów.

GET/locations

Lista salonów

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: listLocations

Salony (lokalizacje) konta, posortowane po identyfikatorze. accepts_online_bookings mówi, czy salon przyjmuje rezerwacje online; katalog usług i specjalistek odpowiada także dla salonu, który ich nie przyjmuje.

Parametry
Parametry
ParametrGdzieOpis
limitzapytanieLiczba elementów na stronie (1-100, domyślnie 50).
cursorzapytanieKursor następnej strony z pola next_cursor poprzedniej odpowiedzi. Nieprzezroczysty; zły kursor = 400 invalid_cursor.
Odpowiedź 200 · LocationList

Strona listy salonów.

Pola odpowiedzi Lista salonów
PoleTypUwagi
datawymaganearray<Location>
data[].idwymaganestring
data[].namewymaganestring
data[].addresswymaganestring | null
data[].citywymaganestring | null
data[].phonewymaganestring | null
data[].timezonewymaganestring
data[].accepts_online_bookingswymaganeboolean
next_cursorwymaganestring | null
Kody odpowiedzi
GET /locations
curl "https://app.silkcrm.net/api/rest/v1/locations" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "data": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000001",
      "name": "Salon Alicja - Centrum",
      "address": "ul. Marszałkowska 10",
      "city": "Warszawa",
      "phone": "+48221234567",
      "timezone": "Europe/Warsaw",
      "accepts_online_bookings": true
    },
    {
      "id": "8f1c0000-0000-4000-8000-000000000002",
      "name": "Salon Alicja - Mokotów",
      "address": "ul. Puławska 120",
      "city": "Warszawa",
      "phone": "+48221234567",
      "timezone": "Europe/Warsaw",
      "accepts_online_bookings": false
    }
  ],
  "next_cursor": null
}

GET/locations/{location_id}/services

Usługi salonu

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: listServices

Usługi widoczne online (bez archiwalnych i ukrytych, dostępnych tylko z linku). Odpowiada także dla salonu, który nie przyjmuje rezerwacji online (patrz accepts_online_bookings w GET /locations). Ceny w groszach; price_mode mówi, które pola ceny są wypełnione.

Parametry
Parametry
ParametrGdzieOpis
location_idwymaganyścieżkaIdentyfikator salonu z GET /locations. Obcy i nieistniejący salon = ten sam 404.
limitzapytanieLiczba elementów na stronie (1-100, domyślnie 50).
cursorzapytanieKursor następnej strony z pola next_cursor poprzedniej odpowiedzi. Nieprzezroczysty; zły kursor = 400 invalid_cursor.
Odpowiedź 200 · ServiceList

Strona listy usług.

Pola odpowiedzi Usługi salonu
PoleTypUwagi
datawymaganearray<Service>
data[].idwymaganestring
data[].namewymaganestring
data[].categorywymaganestring | null
data[].duration_minuteswymaganeinteger≥ 0
data[].price_modewymaganestringjedno z: fixed, range, per_hour, from
data[].price_centswymaganeobject
data[].price_min_centswymaganeobject
data[].price_max_centswymaganeobject
data[].variantswymaganearray<ServiceVariant>
data[].variants[].keywymaganestring
data[].variants[].namewymaganestring
data[].variants[].price_centswymaganeinteger≥ 0
data[].variants[].duration_minuteswymaganeinteger≥ 0
data[].requires_specialistwymaganeboolean
next_cursorwymaganestring | null
Kody odpowiedzi
GET /locations/{location_id}/services
curl "https://app.silkcrm.net/api/rest/v1/locations/8f1c0000-0000-4000-8000-000000000001/services" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "data": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000003",
      "name": "Manicure hybrydowy",
      "category": "Paznokcie",
      "duration_minutes": 60,
      "price_mode": "fixed",
      "price_cents": 12000,
      "price_min_cents": null,
      "price_max_cents": null,
      "variants": [],
      "requires_specialist": true
    },
    {
      "id": "8f1c0000-0000-4000-8000-000000000004",
      "name": "Strzyżenie damskie",
      "category": "Fryzjerstwo",
      "duration_minutes": 45,
      "price_mode": "range",
      "price_cents": null,
      "price_min_cents": 10000,
      "price_max_cents": 16000,
      "variants": [
        {
          "key": "krotkie",
          "name": "Krótkie",
          "price_cents": 10000,
          "duration_minutes": 45
        },
        {
          "key": "dlugie",
          "name": "Długie",
          "price_cents": 16000,
          "duration_minutes": 45
        }
      ],
      "requires_specialist": true
    }
  ],
  "next_cursor": null
}

GET/locations/{location_id}/specialists

Specjalistki salonu

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: listSpecialists

Osoby przyjmujące klientki w salonie. service_ids wskazuje wyłącznie usługi z GET /locations/{location_id}/services (widoczne online). Odpowiada także dla salonu bez rezerwacji online.

Parametry
Parametry
ParametrGdzieOpis
location_idwymaganyścieżkaIdentyfikator salonu z GET /locations. Obcy i nieistniejący salon = ten sam 404.
limitzapytanieLiczba elementów na stronie (1-100, domyślnie 50).
cursorzapytanieKursor następnej strony z pola next_cursor poprzedniej odpowiedzi. Nieprzezroczysty; zły kursor = 400 invalid_cursor.
Odpowiedź 200 · SpecialistList

Strona listy specjalistek.

Pola odpowiedzi Specjalistki salonu
PoleTypUwagi
datawymaganearray<Specialist>
data[].idwymaganestring
data[].display_namewymaganestring
data[].service_idswymaganearray<string>
next_cursorwymaganestring | null
Kody odpowiedzi
GET /locations/{location_id}/specialists
curl "https://app.silkcrm.net/api/rest/v1/locations/8f1c0000-0000-4000-8000-000000000001/specialists" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "data": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000005",
      "display_name": "Kasia",
      "service_ids": [
        "8f1c0000-0000-4000-8000-000000000003",
        "8f1c0000-0000-4000-8000-000000000004"
      ]
    }
  ],
  "next_cursor": null
}

GET/pass-templates

Szablony karnetów

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: listPassTemplates

Aktywne szablony karnetów ze stałą ceną. Sklep może sprzedać wyłącznie szablon z sellable: true (salon sprzedaje go poza kasą). Szablony promocyjne („N-ty zabieg za X zł”) nie mają stałej ceny i nie pojawiają się na liście.

Parametry
Parametry
ParametrGdzieOpis
limitzapytanieLiczba elementów na stronie (1-100, domyślnie 50).
cursorzapytanieKursor następnej strony z pola next_cursor poprzedniej odpowiedzi. Nieprzezroczysty; zły kursor = 400 invalid_cursor.
Odpowiedź 200 · PassTemplateList

Strona listy szablonów karnetów.

Pola odpowiedzi Szablony karnetów
PoleTypUwagi
datawymaganearray<PassTemplate>
data[].idwymaganestring
data[].namewymaganestring
data[].descriptionwymaganestring | null
data[].uses_totalwymaganeinteger≥ 1
data[].price_centswymaganeinteger≥ 0
data[].validity_dayswymaganeobject
data[].service_idswymaganearray<string>
data[].sellablewymaganeboolean
next_cursorwymaganestring | null
Kody odpowiedzi
GET /pass-templates
curl "https://app.silkcrm.net/api/rest/v1/pass-templates" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "data": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000006",
      "name": "Karnet 5 manicure",
      "description": "Pięć wizyt manicure hybrydowego.",
      "uses_total": 5,
      "price_cents": 50000,
      "validity_days": 365,
      "service_ids": [
        "8f1c0000-0000-4000-8000-000000000003"
      ],
      "sellable": true
    }
  ],
  "next_cursor": null
}

Klientki

Karta klientki salonu po telefonie lub e-mailu z zamówienia.

POST/clients/resolve

Znajdź albo załóż kartę klientki

Zakres klucza: write:commerceLimit: 60 zapytań na minutęoperationId: resolveClient

Dopasowuje klientkę po telefonie (dowolny zapis, np. 500 100 200, +48 500-100-200), a bez niego po e-mailu; brak dopasowania zakłada nową kartę. Odpowiedź niesie wyłącznie identyfikator karty, nigdy dane osobowe. Dane istniejącej karty nie są nadpisywane.

Zgody marketingowe ze sklepu: wyłącznie NADANIE (granted: true z chwilą udzielenia). Zgoda jest pomijana, gdy jest starsza niż ostatnie cofnięcie tego kanału przez klientkę; zgoda e-mail nie wraca nigdy po odbiciu albo skardze u dostawcy poczty.

Karta nie jest wiązana z pozycją zamówienia - jedna klientka obsługuje wiele zamówień. W dry-runie nowa karta ma client_id: null.

Wymaga zakresu write:commerce i nagłówka Idempotency-Key. Treść jest walidowana PRZED kontrolą klucza idempotencji (zła treść = 400 invalid_request także bez klucza). Silk-Dry-Run: 1 wykonuje całą operację i ją wycofuje.

Parametry
Parametry
ParametrGdzieOpis
Idempotency-KeywymaganynagłówekKlucz idempotencji zapisu, osobny dla każdego klucza API. Ten sam klucz i ta sama treść = powtórka zapisanej odpowiedzi; ta sama wartość z inną treścią = 409 idempotency_key_reused. Brak = 400 idempotency_key_required, zły format = 400 invalid_request.
Silk-Dry-Runnagłówek1 = próba bez skutków (zapis wycofany), 0 albo brak = zwykły zapis. Każda inna wartość = 400 invalid_request.
Treść żądania

Treść POST /clients/resolve.

Pola żądania Znajdź albo załóż kartę klientki
PoleTypUwagi
external_order_idwymaganestring1-100 znaków
external_order_line_idstringdo 100 znaków
shopstringjedno z: shopify, woocommerce, other
clientwymaganeClientInput
client.phonestring1-40 znaków
client.emailstringformat email · do 255 znaków
client.first_namestring1-100 znaków
client.last_namestringdo 100 znaków
client.consentsobject
client.consents.smsConsentGrant
client.consents.sms.grantedwymaganebooleanzawsze true
client.consents.sms.granted_atwymaganestringformat date-time
client.consents.emailConsentGrant
client.consents.email.grantedwymaganebooleanzawsze true
client.consents.email.granted_atwymaganestringformat date-time
Odpowiedź 200 · ResolveClientResponse

Identyfikator karty klientki, bez danych osobowych.

Pola odpowiedzi Znajdź albo załóż kartę klientki
PoleTypUwagi
dry_runwymaganeboolean
client_idwymaganestring | null
createdwymaganeboolean
Kody odpowiedzi
POST /clients/resolve
curl -X POST "https://app.silkcrm.net/api/rest/v1/clients/resolve" \
  -H "Authorization: Bearer $SILK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1043-client' \
  -d '{
  "external_order_id": "#1043",
  "shop": "shopify",
  "client": {
    "phone": "500 100 200",
    "email": "anna.nowak@example.com",
    "first_name": "Anna",
    "last_name": "Nowak",
    "consents": {
      "sms": {
        "granted": true,
        "granted_at": "2026-11-03T10:00:00.000Z"
      }
    }
  }
}'
OdpowiedźJSON
HTTP 200

{
  "dry_run": false,
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "created": true
}

Vouchery

Vouchery kwotowe sprzedane w sklepie: wydanie, odczyt, zwrot.

POST/vouchers

Wydaj voucher kwotowy

Zakres klucza: write:commerceLimit: 60 zapytań na minutęoperationId: createVoucher

Voucher kwotowy sprzedany w sklepie. Odbiorczyni to DOKŁADNIE jedno z: client_id, client (znajdź albo załóż kartę) i recipient_phone (numer bez karty - voucher czeka pod nim). Opcjonalna purchaser to osoba płacąca, gdy voucher jest prezentem.

paid_cents < amount_cents = sprzedaż z rabatem: wartość vouchera zostaje pełna, zapłata trafia do paid_cents. Kwota musi mieścić się w zakresie ustawionym przez salon (422 voucher_amount_out_of_range z details.min_cents/max_cents).

VAT i fiskalizacja: sprzedaż vouchera to wpłata na bon wielokrotnego przeznaczenia - sklep NIE wystawia za nią paragonu fiskalnego, salon fiskalizuje przy realizacji vouchera. Silk niczego nie wysyła klientce (ani SMS, ani e-mail).

Pozycja zamówienia (external_order_id + external_order_line_id + shop) realizuje się raz: drugi zapis tej pozycji innym kluczem idempotencji = 409 order_line_already_fulfilled z details.existing_id.

Wymaga zakresu write:commerce i nagłówka Idempotency-Key. Treść jest walidowana PRZED kontrolą klucza idempotencji (zła treść = 400 invalid_request także bez klucza). Silk-Dry-Run: 1 wykonuje całą operację i ją wycofuje.

Parametry
Parametry
ParametrGdzieOpis
Idempotency-KeywymaganynagłówekKlucz idempotencji zapisu, osobny dla każdego klucza API. Ten sam klucz i ta sama treść = powtórka zapisanej odpowiedzi; ta sama wartość z inną treścią = 409 idempotency_key_reused. Brak = 400 idempotency_key_required, zły format = 400 invalid_request.
Silk-Dry-Runnagłówek1 = próba bez skutków (zapis wycofany), 0 albo brak = zwykły zapis. Każda inna wartość = 400 invalid_request.
Treść żądania

Treść POST /vouchers: dokładnie jedno z client_id, client, recipient_phone.

Pola żądania Wydaj voucher kwotowy
PoleTypUwagi
external_order_idwymaganestring1-100 znaków
external_order_line_idstringdo 100 znaków
shopstringjedno z: shopify, woocommerce, other
amount_centswymaganeinteger≥ 1
paid_centswymaganeinteger≥ 0
client_idstring1-100 znaków
clientClientInput
client.phonestring1-40 znaków
client.emailstringformat email · do 255 znaków
client.first_namestring1-100 znaków
client.last_namestringdo 100 znaków
client.consentsobject
client.consents.smsConsentGrant
client.consents.sms.grantedwymaganebooleanzawsze true
client.consents.sms.granted_atwymaganestringformat date-time
client.consents.emailConsentGrant
client.consents.email.grantedwymaganebooleanzawsze true
client.consents.email.granted_atwymaganestringformat date-time
recipient_phonestring1-40 znaków
purchaserPurchaserInput
purchaser.client_idstring1-100 znaków
purchaser.clientClientInput
purchaser.client.phonestring1-40 znaków
purchaser.client.emailstringformat email · do 255 znaków
purchaser.client.first_namestring1-100 znaków
purchaser.client.last_namestringdo 100 znaków
purchaser.client.consentsobject
purchaser.client.consents.smsConsentGrant
purchaser.client.consents.sms.grantedwymaganebooleanzawsze true
purchaser.client.consents.sms.granted_atwymaganestringformat date-time
purchaser.client.consents.emailConsentGrant
purchaser.client.consents.email.grantedwymaganebooleanzawsze true
purchaser.client.consents.email.granted_atwymaganestringformat date-time
gift_messagestringdo 500 znaków
Odpowiedź 201 · Voucher

Voucher kwotowy. amount_cents = wartość, balance_cents = saldo, paid_cents = zapłata w sklepie. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Wydaj voucher kwotowy
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
amount_centswymaganeinteger≥ 0
balance_centswymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
client_idwymaganestring | null
recipient_phonewymaganestring | null
purchaser_client_idwymaganestring | null
gift_messagewymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
POST /vouchers
curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers" \
  -H "Authorization: Bearer $SILK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1043-voucher' \
  -d '{
  "external_order_id": "#1043",
  "external_order_line_id": "1",
  "shop": "shopify",
  "amount_cents": 20000,
  "paid_cents": 18000,
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "gift_message": "Wszystkiego najlepszego!"
}'
OdpowiedźJSON
HTTP 201

{
  "id": "8f1c0000-0000-4000-8000-000000000008",
  "status": "active",
  "amount_cents": 20000,
  "balance_cents": 20000,
  "paid_cents": 18000,
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "recipient_phone": null,
  "purchaser_client_id": null,
  "gift_message": "Wszystkiego najlepszego!",
  "expires_at": null,
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z",
  "dry_run": false
}

GET/vouchers/{id}

Odczytaj voucher

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: getVoucher

Aktualny stan vouchera: saldo, status, ważność. external_order_id = numer zamówienia sklepu, z którego voucher powstał (null dla vouchera z kasy salonu).

Parametry
Parametry
ParametrGdzieOpis
idwymaganyścieżkaIdentyfikator zwrócony przy wydaniu. Obcy, nieistniejący i obiekt innego rodzaju = ten sam 404.
Odpowiedź 200 · Voucher

Voucher kwotowy. amount_cents = wartość, balance_cents = saldo, paid_cents = zapłata w sklepie. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Odczytaj voucher
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
amount_centswymaganeinteger≥ 0
balance_centswymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
client_idwymaganestring | null
recipient_phonewymaganestring | null
purchaser_client_idwymaganestring | null
gift_messagewymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
GET /vouchers/{id}
curl "https://app.silkcrm.net/api/rest/v1/vouchers/8f1c0000-0000-4000-8000-000000000008" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "id": "8f1c0000-0000-4000-8000-000000000008",
  "status": "active",
  "amount_cents": 20000,
  "balance_cents": 20000,
  "paid_cents": 18000,
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "recipient_phone": null,
  "purchaser_client_id": null,
  "gift_message": "Wszystkiego najlepszego!",
  "expires_at": null,
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z"
}

POST/vouchers/{id}/void

Unieważnij voucher (zwrot w sklepie)

Zakres klucza: write:commerceLimit: 60 zapytań na minutęoperationId: voidVoucher

Zwrot zamówienia w sklepie. Unieważnić można wyłącznie obiekt utworzony przez API dla TEGO SAMEGO zamówienia (external_order_id + shop z treści; pozycja nie musi się zgadzać). Voucher lub karnet z kasy salonu, z innego zamówienia, obcy, innego rodzaju i nieistniejący dają ten sam 404 not_found. Obiekt zrealizowany choćby w części (każda niezwrócona realizacja, także voucher wykorzystany w całości albo wygasły po realizacji) = 409 fund_partially_used; zamknięty bez niezwróconej realizacji (już unieważniony, wygasły nietknięty) = 409 fund_already_closed.

Wymaga zakresu write:commerce i nagłówka Idempotency-Key. Treść jest walidowana PRZED kontrolą klucza idempotencji (zła treść = 400 invalid_request także bez klucza). Silk-Dry-Run: 1 wykonuje całą operację i ją wycofuje.

Parametry
Parametry
ParametrGdzieOpis
idwymaganyścieżkaIdentyfikator zwrócony przy wydaniu. Obcy, nieistniejący i obiekt innego rodzaju = ten sam 404.
Idempotency-KeywymaganynagłówekKlucz idempotencji zapisu, osobny dla każdego klucza API. Ten sam klucz i ta sama treść = powtórka zapisanej odpowiedzi; ta sama wartość z inną treścią = 409 idempotency_key_reused. Brak = 400 idempotency_key_required, zły format = 400 invalid_request.
Silk-Dry-Runnagłówek1 = próba bez skutków (zapis wycofany), 0 albo brak = zwykły zapis. Każda inna wartość = 400 invalid_request.
Treść żądania

Treść zwrotu: numer zamówienia, z którego powstał obiekt; reason domyślnie „Zwrot w sklepie internetowym”.

Pola żądania Unieważnij voucher (zwrot w sklepie)
PoleTypUwagi
external_order_idwymaganestring1-100 znaków
external_order_line_idstringdo 100 znaków
shopstringjedno z: shopify, woocommerce, other
reasonstringdo 200 znaków
Odpowiedź 200 · Voucher

Voucher kwotowy. amount_cents = wartość, balance_cents = saldo, paid_cents = zapłata w sklepie. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Unieważnij voucher (zwrot w sklepie)
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
amount_centswymaganeinteger≥ 0
balance_centswymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
client_idwymaganestring | null
recipient_phonewymaganestring | null
purchaser_client_idwymaganestring | null
gift_messagewymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
POST /vouchers/{id}/void
curl -X POST "https://app.silkcrm.net/api/rest/v1/vouchers/8f1c0000-0000-4000-8000-000000000008/void" \
  -H "Authorization: Bearer $SILK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1043-refund-voucher' \
  -d '{
  "external_order_id": "#1043",
  "shop": "shopify",
  "reason": "Klientka zwróciła zamówienie"
}'
OdpowiedźJSON
HTTP 200

{
  "id": "8f1c0000-0000-4000-8000-000000000008",
  "status": "void",
  "amount_cents": 20000,
  "balance_cents": 0,
  "paid_cents": 18000,
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "recipient_phone": null,
  "purchaser_client_id": null,
  "gift_message": "Wszystkiego najlepszego!",
  "expires_at": null,
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z",
  "dry_run": false
}

Karnety

Karnety sprzedane w sklepie: wydanie, odczyt, zwrot.

POST/passes

Wydaj karnet

Zakres klucza: write:commerceLimit: 60 zapytań na minutęoperationId: createPass

Karnet z szablonu, który salon sprzedaje poza kasą (sellable: true w GET /pass-templates). Karnet wymaga karty klientki: DOKŁADNIE jedno z client_id i client.

paid_cents mniejsze od ceny szablonu = sprzedaż z rabatem: liczba wejść zostaje z szablonu, wartość jednego wejścia (unit_value_cents) liczy się od zapłaty.

VAT i fiskalizacja: sprzedaż karnetu fiskalizuje sklep - Silk nie wystawia paragonu. Silk niczego nie wysyła klientce.

Pozycja zamówienia realizuje się raz: drugi zapis tej pozycji innym kluczem idempotencji = 409 order_line_already_fulfilled z details.existing_id.

Wymaga zakresu write:commerce i nagłówka Idempotency-Key. Treść jest walidowana PRZED kontrolą klucza idempotencji (zła treść = 400 invalid_request także bez klucza). Silk-Dry-Run: 1 wykonuje całą operację i ją wycofuje.

Parametry
Parametry
ParametrGdzieOpis
Idempotency-KeywymaganynagłówekKlucz idempotencji zapisu, osobny dla każdego klucza API. Ten sam klucz i ta sama treść = powtórka zapisanej odpowiedzi; ta sama wartość z inną treścią = 409 idempotency_key_reused. Brak = 400 idempotency_key_required, zły format = 400 invalid_request.
Silk-Dry-Runnagłówek1 = próba bez skutków (zapis wycofany), 0 albo brak = zwykły zapis. Każda inna wartość = 400 invalid_request.
Treść żądania

Treść POST /passes: dokładnie jedno z client_id i client.

Pola żądania Wydaj karnet
PoleTypUwagi
external_order_idwymaganestring1-100 znaków
external_order_line_idstringdo 100 znaków
shopstringjedno z: shopify, woocommerce, other
template_idwymaganestring1-100 znaków
paid_centswymaganeinteger≥ 0
client_idstring1-100 znaków
clientClientInput
client.phonestring1-40 znaków
client.emailstringformat email · do 255 znaków
client.first_namestring1-100 znaków
client.last_namestringdo 100 znaków
client.consentsobject
client.consents.smsConsentGrant
client.consents.sms.grantedwymaganebooleanzawsze true
client.consents.sms.granted_atwymaganestringformat date-time
client.consents.emailConsentGrant
client.consents.email.grantedwymaganebooleanzawsze true
client.consents.email.granted_atwymaganestringformat date-time
Odpowiedź 201 · Pass

Karnet. uses_left = pozostałe wejścia, unit_value_cents = wartość jednego wejścia. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Wydaj karnet
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
template_idwymaganestring | null
namewymaganestring
uses_totalwymaganeinteger≥ 0
uses_leftwymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
unit_value_centswymaganeobject
service_idswymaganearray<string>
client_idwymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
POST /passes
curl -X POST "https://app.silkcrm.net/api/rest/v1/passes" \
  -H "Authorization: Bearer $SILK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1043-pass' \
  -d '{
  "external_order_id": "#1043",
  "external_order_line_id": "3",
  "shop": "shopify",
  "template_id": "8f1c0000-0000-4000-8000-000000000006",
  "paid_cents": 45000,
  "client_id": "8f1c0000-0000-4000-8000-000000000007"
}'
OdpowiedźJSON
HTTP 201

{
  "id": "8f1c0000-0000-4000-8000-000000000009",
  "status": "active",
  "template_id": "8f1c0000-0000-4000-8000-000000000006",
  "name": "Karnet 5 manicure",
  "uses_total": 5,
  "uses_left": 5,
  "paid_cents": 45000,
  "unit_value_cents": 9000,
  "service_ids": [
    "8f1c0000-0000-4000-8000-000000000003"
  ],
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "expires_at": "2027-11-03T10:15:00.000Z",
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z",
  "dry_run": false
}

GET/passes/{id}

Odczytaj karnet

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: getPass

Aktualny stan karnetu: pozostałe wejścia, status, ważność. external_order_id = numer zamówienia sklepu, z którego karnet powstał (null dla karnetu z kasy salonu).

Parametry
Parametry
ParametrGdzieOpis
idwymaganyścieżkaIdentyfikator zwrócony przy wydaniu. Obcy, nieistniejący i obiekt innego rodzaju = ten sam 404.
Odpowiedź 200 · Pass

Karnet. uses_left = pozostałe wejścia, unit_value_cents = wartość jednego wejścia. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Odczytaj karnet
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
template_idwymaganestring | null
namewymaganestring
uses_totalwymaganeinteger≥ 0
uses_leftwymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
unit_value_centswymaganeobject
service_idswymaganearray<string>
client_idwymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
GET /passes/{id}
curl "https://app.silkcrm.net/api/rest/v1/passes/8f1c0000-0000-4000-8000-000000000009" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "id": "8f1c0000-0000-4000-8000-000000000009",
  "status": "active",
  "template_id": "8f1c0000-0000-4000-8000-000000000006",
  "name": "Karnet 5 manicure",
  "uses_total": 5,
  "uses_left": 5,
  "paid_cents": 45000,
  "unit_value_cents": 9000,
  "service_ids": [
    "8f1c0000-0000-4000-8000-000000000003"
  ],
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "expires_at": "2027-11-03T10:15:00.000Z",
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z"
}

POST/passes/{id}/void

Unieważnij karnet (zwrot w sklepie)

Zakres klucza: write:commerceLimit: 60 zapytań na minutęoperationId: voidPass

Zwrot zamówienia w sklepie. Unieważnić można wyłącznie obiekt utworzony przez API dla TEGO SAMEGO zamówienia (external_order_id + shop z treści; pozycja nie musi się zgadzać). Voucher lub karnet z kasy salonu, z innego zamówienia, obcy, innego rodzaju i nieistniejący dają ten sam 404 not_found. Obiekt zrealizowany choćby w części (każda niezwrócona realizacja, także voucher wykorzystany w całości albo wygasły po realizacji) = 409 fund_partially_used; zamknięty bez niezwróconej realizacji (już unieważniony, wygasły nietknięty) = 409 fund_already_closed.

Wymaga zakresu write:commerce i nagłówka Idempotency-Key. Treść jest walidowana PRZED kontrolą klucza idempotencji (zła treść = 400 invalid_request także bez klucza). Silk-Dry-Run: 1 wykonuje całą operację i ją wycofuje.

Parametry
Parametry
ParametrGdzieOpis
idwymaganyścieżkaIdentyfikator zwrócony przy wydaniu. Obcy, nieistniejący i obiekt innego rodzaju = ten sam 404.
Idempotency-KeywymaganynagłówekKlucz idempotencji zapisu, osobny dla każdego klucza API. Ten sam klucz i ta sama treść = powtórka zapisanej odpowiedzi; ta sama wartość z inną treścią = 409 idempotency_key_reused. Brak = 400 idempotency_key_required, zły format = 400 invalid_request.
Silk-Dry-Runnagłówek1 = próba bez skutków (zapis wycofany), 0 albo brak = zwykły zapis. Każda inna wartość = 400 invalid_request.
Treść żądania

Treść zwrotu: numer zamówienia, z którego powstał obiekt; reason domyślnie „Zwrot w sklepie internetowym”.

Pola żądania Unieważnij karnet (zwrot w sklepie)
PoleTypUwagi
external_order_idwymaganestring1-100 znaków
external_order_line_idstringdo 100 znaków
shopstringjedno z: shopify, woocommerce, other
reasonstringdo 200 znaków
Odpowiedź 200 · Pass

Karnet. uses_left = pozostałe wejścia, unit_value_cents = wartość jednego wejścia. W dry-runie pola obiektów, które dopiero by powstały, są null.

Pola odpowiedzi Unieważnij karnet (zwrot w sklepie)
PoleTypUwagi
idwymaganestring | null
statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
template_idwymaganestring | null
namewymaganestring
uses_totalwymaganeinteger≥ 0
uses_leftwymaganeinteger≥ 0
paid_centswymaganeinteger≥ 0
unit_value_centswymaganeobject
service_idswymaganearray<string>
client_idwymaganestring | null
expires_atwymaganestring | null
external_order_idwymaganestring | null
created_atwymaganestring | null
dry_runboolean
Kody odpowiedzi
POST /passes/{id}/void
curl -X POST "https://app.silkcrm.net/api/rest/v1/passes/8f1c0000-0000-4000-8000-000000000009/void" \
  -H "Authorization: Bearer $SILK_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-1043-refund-pass' \
  -d '{
  "external_order_id": "#1043",
  "shop": "shopify"
}'
OdpowiedźJSON
HTTP 200

{
  "id": "8f1c0000-0000-4000-8000-000000000009",
  "status": "void",
  "template_id": "8f1c0000-0000-4000-8000-000000000006",
  "name": "Karnet 5 manicure",
  "uses_total": 5,
  "uses_left": 0,
  "paid_cents": 45000,
  "unit_value_cents": 9000,
  "service_ids": [
    "8f1c0000-0000-4000-8000-000000000003"
  ],
  "client_id": "8f1c0000-0000-4000-8000-000000000007",
  "expires_at": "2027-11-03T10:15:00.000Z",
  "external_order_id": "#1043",
  "created_at": "2026-11-03T10:15:00.000Z",
  "dry_run": false
}

Zamówienia

Wszystko, co Silk utworzył dla zamówienia sklepu.

GET/orders/{external_order_id}

Stan zamówienia sklepu w Silku

Zakres klucza: read:*Limit: 120 zapytań na minutęoperationId: getOrder

Vouchery i karnety utworzone przez API dla numeru zamówienia, w aktualnym stanie (po zwrocie status void). Numer zamówienia jest przycinany ze spacji; # koduj jako %23. Brak czegokolwiek dla tego numeru = 404 not_found.

Parametry
Parametry
ParametrGdzieOpis
external_order_idwymaganyścieżkaNumer zamówienia sklepu, przycinany ze spacji, wielkość liter ma znaczenie. Znak # koduj jako %23 (np. /orders/%231043) - surowy # zaczyna fragment adresu i nie dociera do serwera.
shopzapytanieZawęża do zamówień jednego sklepu. Bez parametru: wszystkie sklepy, a przy kilku shop w odpowiedzi = null.
Odpowiedź 200 · Order

Vouchery i karnety utworzone przez API dla zamówienia sklepu.

Pola odpowiedzi Stan zamówienia sklepu w Silku
PoleTypUwagi
external_order_idwymaganestring
shopwymaganeobject
voucherswymaganearray<Voucher>
vouchers[].idwymaganestring | null
vouchers[].statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
vouchers[].amount_centswymaganeinteger≥ 0
vouchers[].balance_centswymaganeinteger≥ 0
vouchers[].paid_centswymaganeinteger≥ 0
vouchers[].client_idwymaganestring | null
vouchers[].recipient_phonewymaganestring | null
vouchers[].purchaser_client_idwymaganestring | null
vouchers[].gift_messagewymaganestring | null
vouchers[].expires_atwymaganestring | null
vouchers[].external_order_idwymaganestring | null
vouchers[].created_atwymaganestring | null
vouchers[].dry_runboolean
passeswymaganearray<Pass>
passes[].idwymaganestring | null
passes[].statuswymaganestringjedno z: pending_payment, active, used_up, expired, void
passes[].template_idwymaganestring | null
passes[].namewymaganestring
passes[].uses_totalwymaganeinteger≥ 0
passes[].uses_leftwymaganeinteger≥ 0
passes[].paid_centswymaganeinteger≥ 0
passes[].unit_value_centswymaganeobject
passes[].service_idswymaganearray<string>
passes[].client_idwymaganestring | null
passes[].expires_atwymaganestring | null
passes[].external_order_idwymaganestring | null
passes[].created_atwymaganestring | null
passes[].dry_runboolean
Kody odpowiedzi
GET /orders/{external_order_id}
curl "https://app.silkcrm.net/api/rest/v1/orders/%231043" \
  -H "Authorization: Bearer $SILK_API_KEY"
OdpowiedźJSON
HTTP 200

{
  "external_order_id": "#1043",
  "shop": "shopify",
  "vouchers": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000008",
      "status": "active",
      "amount_cents": 20000,
      "balance_cents": 20000,
      "paid_cents": 18000,
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "recipient_phone": null,
      "purchaser_client_id": null,
      "gift_message": "Wszystkiego najlepszego!",
      "expires_at": null,
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z"
    }
  ],
  "passes": [
    {
      "id": "8f1c0000-0000-4000-8000-000000000009",
      "status": "active",
      "template_id": "8f1c0000-0000-4000-8000-000000000006",
      "name": "Karnet 5 manicure",
      "uses_total": 5,
      "uses_left": 5,
      "paid_cents": 45000,
      "unit_value_cents": 9000,
      "service_ids": [
        "8f1c0000-0000-4000-8000-000000000003"
      ],
      "client_id": "8f1c0000-0000-4000-8000-000000000007",
      "expires_at": "2027-11-03T10:15:00.000Z",
      "external_order_id": "#1043",
      "created_at": "2026-11-03T10:15:00.000Z"
    }
  ]
}

Błędy

Kształt błędu i kody

Każdy błąd ma ten sam kształt: { "error": { "code", "message", "details"?, "request_id" } }. Rozgałęziaj się po code (lista w schemacie Error, pole x-error-codes), nie po treści message (po polsku, może się zmienić). request_id podaj przy zgłoszeniu. Obcy i nieistniejący zasób to ten sam 404 not_found.

Przykład błędu 422JSON
{
  "error": {
    "code": "voucher_amount_out_of_range",
    "message": "Kwota vouchera jest poza zakresem ustawionym przez salon.",
    "details": { "min_cents": 5000, "max_cents": 50000 },
    "request_id": "req-8f1c0001"
  }
}
Kody błędów REST API v1
KodHTTPZnaczenie
unauthorized401Brak ważnego klucza API. Podaj go w nagłówku Authorization: Bearer silk_live_….
api_key_required403To API przyjmuje wyłącznie klucz API salonu (silk_live_…), nie inne sposoby logowania.
insufficient_scope403Klucz API nie ma uprawnienia do tej operacji. Zapisy wymagają zakresu write:commerce.
feature_not_available_on_plan403Plan salonu nie obejmuje dostępu przez API.
tenant_suspended403Konto salonu jest zawieszone. Skontaktuj się z obsługą SilkCRM.
rate_limited429Przekroczono limit zapytań. Spróbuj ponownie za chwilę.
invalid_request400Zapytanie ma niepoprawne parametry albo treść.
invalid_cursor400Kursor stronicowania jest nieprawidłowy. Pobierz listę od początku.
not_found404Nie znaleziono zasobu.
idempotency_key_required400Zapis wymaga nagłówka Idempotency-Key.
idempotency_key_reused409Ten Idempotency-Key był już użyty z inną treścią zapytania.
order_line_already_fulfilled409Ta pozycja zamówienia została już zrealizowana.
client_not_found422Nie znaleziono klientki salonu.
client_identity_required422Podaj numer telefonu albo adres e-mail klientki.
client_limit_reached422Salon osiągnął limit klientek w swoim planie.
vouchers_disabled422Salon nie sprzedaje voucherów.
voucher_amount_out_of_range422Kwota vouchera jest poza zakresem ustawionym przez salon.
passes_disabled422Salon nie sprzedaje karnetów.
pass_template_not_sellable422Tego karnetu nie można sprzedać.
pass_template_promotional422Karnetu promocyjnego nie można sprzedać przez API.
payment_exceeds_value422Kwota zapłaty przekracza wartość vouchera lub karnetu.
fund_partially_used409Voucher lub karnet został już częściowo wykorzystany.
fund_already_closed409Voucher lub karnet jest już zamknięty.
internal_error500Wystąpił błąd po stronie Silk. Spróbuj ponownie; jeśli się powtarza, podaj request_id.

Limity

Limity zapytań

Limity liczą się osobno dla każdej trasy i każdego klucza API: odczyty 120 zapytań na minutę, zapisy 60 zapytań na minutę (osobne liczniki). Po przekroczeniu: 429 rate_limited z details.retry_after (sekundy) i nagłówkiem Retry-After.

Limity zapytań
RodzajLimitLicznik
Odczyt (GET)120 zapytań na minutęosobno dla każdej trasy i każdego klucza API
Zapis (POST)60 zapytań na minutęosobny licznik zapisów, dla każdej trasy i każdego klucza API

Idempotencja

Ponawianie zapisów bez duplikatów

Każdy zapis wymaga nagłówka Idempotency-Key (1-255 znaków A-Z a-z 0-9 _ - : .). Ponowienie z tym samym kluczem i tą samą treścią zwraca zapisaną odpowiedź z nagłówkiem Idempotent-Replay: true - bez drugiego skutku.

  • Klucze są osobne dla każdego klucza API: nowy klucz API to nowa przestrzeń kluczy idempotencji.
  • Porównywane są metoda, ścieżka i treść (bez query string). Ten sam klucz z inną treścią = 409 idempotency_key_reused. Ścieżka jest porównywana dosłownie, więc ten sam klucz z inaczej zapisaną ścieżką (ukośnik na końcu, inne kodowanie identyfikatora) też daje 409 idempotency_key_reused.
  • Zapamiętywane są wyłącznie odpowiedzi 2xx. Po błędzie ten sam klucz można ponowić z poprawioną treścią.
  • Równoległe żądanie z tym samym kluczem czeka na pierwsze i dostaje jego odpowiedź jako powtórkę.
  • Treść jest walidowana przed kontrolą klucza: zła treść daje 400 invalid_request nawet bez nagłówka.
  • Niezależnie od klucza pozycja zamówienia (external_order_id + external_order_line_id + shop) realizuje się raz: 409 order_line_already_fulfilled z details.existing_id.

Dobry klucz idempotencji to numer zamówienia i pozycji, np. order-1043-voucher. Przykład powtórki: ponowione powiadomienie sklepu.

Dry-run

Próba bez skutków

Nagłówek Silk-Dry-Run: 1 wykonuje zapis w całości i go wycofuje: odpowiedź ma "dry_run": true, nagłówek Silk-Dry-Run: 1, a obiekty, które dopiero by powstały, mają id: null. Brak nagłówka albo 0 = zwykły zapis; każda inna wartość = 400 invalid_request. Dry-run z kluczem idempotencji już użytym w prawdziwym zapisie zwraca zapisaną PRAWDZIWĄ odpowiedź (z "dry_run": false) oraz Silk-Dry-Run: 1.

Wartości nagłówka Silk-Dry-Run
Nagłówek Silk-Dry-RunSkutek
1Próba: zapis wykonany i wycofany, odpowiedź z dry_run: true i nagłówkiem Silk-Dry-Run: 1
0 albo brakZwykły zapis
każda inna wartość400 invalid_request

Konwencje

Konwencje i zamówienia sklepu

Kwoty w groszach (*_cents, liczby całkowite). Czasy w ISO 8601. Identyfikatory to nieprzezroczyste napisy (UUID). Listy są stronicowane kursorem (limit, cursor → next_cursor, null = ostatnia strona).

Zamówienia sklepu

Każdy zapis podaje external_order_id (1-100 znaków, przycinany ze spacji), opcjonalnie external_order_line_id i shop (shopify, woocommerce, other - domyślnie other). W ścieżce (GET /orders/{external_order_id}) znak # koduj jako %23. Unieważnić (zwrot) można wyłącznie obiekt utworzony przez API dla tego samego zamówienia (external_order_id + shop) - każdy inny przypadek to 404.

Dane osobowe

Klientki i zgody

Odpowiedzi nie niosą danych osobowych - wyłącznie identyfikatory kart (wyjątek: recipient_phone, który podał sam sklep). Zgody marketingowe ze sklepu to wyłącznie nadanie; zgoda starsza niż ostatnie cofnięcie kanału jest pomijana, a zgoda e-mail nie wraca nigdy po odbiciu albo skardze u dostawcy poczty. Silk niczego nie wysyła klientce przy wydaniu vouchera ani karnetu.

Fiskalizacja

VAT i fiskalizacja

Voucher kwotowy: sprzedaż to wpłata na bon wielokrotnego przeznaczenia - sklep NIE wystawia paragonu fiskalnego, salon fiskalizuje przy realizacji. Karnet: sprzedaż fiskalizuje sklep; Silk nie wystawia paragonu przy sprzedaży ze sklepu.

Kto wystawia paragon
ProduktSprzedaż w sklepieKiedy powstaje paragon
Voucher kwotowySklep NIE wystawia paragonu fiskalnego: sprzedaż vouchera to wpłata na bon wielokrotnego przeznaczenia.Przy realizacji vouchera w salonie. Paragon wystawia salon.
KarnetSprzedaż fiskalizuje sklep. Silk nie wystawia paragonu przy sprzedaży karnetu ze sklepu.Przy sprzedaży, w sklepie.

To opis tego, jak działa Silk. Rozliczenie podatkowe konkretnego salonu potwierdź z jego księgową.

Webhooki

Webhooki wychodzące

Webhooki powiadamiają Twój system o zdarzeniach w salonie: nowej wizycie, płatności, opinii. To osobny mechanizm od REST API v1: konfiguruje go salon w aplikacji (plany Pro i wyższe), a dostawa nie zależy od klucza API.

Konfiguracja

Ustawienia → Zaawansowane → Webhooki → „Nowy webhook”. Wypełnij „URL endpointu” (publiczny adres Twojego serwera), „Sekret HMAC” (8-500 znaków, wymagany przy tworzeniu), opcjonalny „Opis”, zaznacz „Zdarzenia” i kliknij „Dodaj webhook”. Przycisk „Test” wysyła zdarzenie próbne z polem test: true w data, a tabela „Log dostaw” pokazuje każdą próbę ze statusem i odpowiedzią Twojego serwera.

Zdarzenia

Zdarzenia webhooków
ZdarzenieKiedyPola w data
appointment.createdNowa wizyta została utworzona.appointment_idlocation_idsource
appointment.updatedWizyta została zmieniona.appointment_idstartendspecialist_idestimated_price
appointment.cancelledWizyta została anulowana.appointment_idprevious_statuscancellation_reasonnotecancellation_penalty_amount
appointment.completedWizyta została ukończona.appointment_idprevious_statusnote
client.createdNowy klient został utworzony.client_id
client.updatedProfil klienta został zaktualizowany.client_idchangeslifecycle_stagelead_status
payment.completedPłatność za wizytę została rozliczona.appointment_idreceipt_idsubtotaltotalpayment_idamountmethod
review.receivedOtrzymano opinię klienta po wizycie.review_idratingappointment_idclient_idsource
lead.createdUtworzono nowy lead sprzedażowy.lead_idsourceassigned_tolocation_id

Treść dostawy

Każda dostawa to POST z kopertą zdarzenia. Pole data zależy od typu zdarzenia i może z czasem dostać nowe pola: ignoruj te, których nie znasz.

Koperta zdarzeniaJSON
{
  "id": "6b1f0f7e-3c2a-4d8e-9a51-2f0c7d1e4a10",
  "type": "appointment.created",
  "version": "v1",
  "timestamp": "2026-11-06T09:15:00.000Z",
  "tenant_id": "8f1c0000-0000-4000-8000-0000000000aa",
  "actor": { "id": "8f1c0000-0000-4000-8000-0000000000bb", "type": "user" },
  "data": {
    "appointment_id": "8f1c0000-0000-4000-8000-0000000000cc",
    "location_id": "8f1c0000-0000-4000-8000-000000000001",
    "source": "staff"
  }
}
Nagłówki dostawy webhooka
NagłówekWartośćZnaczenie
Content-Typeapplication/jsonTreść to JSON koperty zdarzenia.
X-BeautyCRM-DeliveryUUID dostawyTen sam przy każdej próbie tej samej dostawy. Użyj go do odrzucania duplikatów.
X-BeautyCRM-Eventnp. appointment.createdTyp zdarzenia.
X-BeautyCRM-Signaturesha256=<hex>HMAC SHA-256 z sekretem endpointu, liczony z timestamp.delivery.treść.
X-BeautyCRM-Timestampnp. 2026-11-06T09:15:00.000ZChwila wysłania tej próby (ISO 8601). Nowa przy każdym ponowieniu.

Weryfikacja podpisu

Podpis to HMAC SHA-256 z sekretem endpointu, liczony z napisu {X-BeautyCRM-Timestamp}.{X-BeautyCRM-Delivery}.{surowa treść}, zapisany szesnastkowo z prefiksem sha256=. Licz go z bajtów, które przyszły, zanim sparsujesz JSON: ponowna serializacja zmienia treść i podpis się nie zgodzi. Porównuj w stałym czasie i odrzucaj dostawy ze znacznikiem czasu starszym niż kilka minut.

Weryfikacja podpisu webhooka
import crypto from "node:crypto";
import express from "express";

const app = express();
const MAX_AGE_MS = 5 * 60 * 1000;
const SECRET = process.env.SILK_WEBHOOK_SECRET;
if (!SECRET) throw new Error("Brak SILK_WEBHOOK_SECRET - ustaw sekret HMAC webhooka.");

// Podpis liczymy z SUROWEJ treści, więc parser JSON-a dopiero po weryfikacji.
app.post("/webhooks/silkcrm", express.raw({ type: "application/json" }), (req, res) => {
  const rawBody = req.body.toString("utf8");
  const timestamp = req.get("X-BeautyCRM-Timestamp") ?? "";
  const deliveryId = req.get("X-BeautyCRM-Delivery") ?? "";
  const signature = req.get("X-BeautyCRM-Signature") ?? "";
  // Zły format nagłówka = 401 od razu (inaczej bufory różnej długości wywróciłyby timingSafeEqual).
  if (!/^sha256=[0-9a-f]{64}$/.test(signature)) return res.status(401).end();

  const expected = crypto
    .createHmac("sha256", SECRET)
    .update(`${timestamp}.${deliveryId}.${rawBody}`)
    .digest();
  const received = Buffer.from(signature.slice("sha256=".length), "hex");

  const valid = crypto.timingSafeEqual(expected, received);
  const age = Math.abs(Date.now() - Date.parse(timestamp));
  if (!valid || !(age < MAX_AGE_MS)) return res.status(401).end();

  const event = JSON.parse(rawBody);
  // Odrzuć duplikat po deliveryId, potem obsłuż event.type i event.data.
  res.status(200).end();
});

Dostawa i ponowienia

  • Sukces to dowolna odpowiedź 2xx w ciągu 10 sekund. Odpowiadaj od razu, a zdarzenie przetwarzaj w tle. Przekierowania (do 5) są śledzone, ale każdy adres musi być publiczny.
  • Silk próbuje dostarczyć zdarzenie 3 razy: od razu, po około minucie i po około 5 minutach. Zadanie ponowień chodzi co 5 minut, więc odstęp bywa dłuższy.
  • Ponowienie ma ten sam X-BeautyCRM-Delivery i nowy X-BeautyCRM-Timestamp. Odrzucaj duplikaty po identyfikatorze dostawy, a nie po treści. Kolejność dostaw nie jest gwarantowana.
  • Po trzeciej nieudanej próbie dostawa zostaje oznaczona jako nieudana, endpoint jest wyłączany, a salon dostaje powiadomienie „Webhook został dezaktywowany”. Po naprawie włącz go przełącznikiem „Endpoint aktywny”. Nieudane dostawy nie są wysyłane ponownie.

CLI

Dane salonu w terminalu

Pakiet @silkcrm/cli (polecenie silk) daje dostęp do narzędzi AI salonu z terminala: przychody, KPI, wizyty, rozliczenia. Używa tego samego klucza API, ale woła narzędzia AI (/api/v1/ai/tools), a nie REST API v1. Wymaga Node.js 20.19.6 lub nowszego.

Instalacja i kluczTerminal
npx @silkcrm/cli --help
# albo globalnie:
npm i -g @silkcrm/cli

export SILK_API_KEY=silk_live_...            # klucz z Ustawień
export SILK_API_URL=https://app.silkcrm.net  # opcjonalnie
PoleceniaTerminal
silk revenue --last 30d
silk kpi --last 7d
silk appointments --from 2026-11-01 --to 2026-11-30
silk billing

silk tools list
silk tools schema aggregate_revenue
silk tools call aggregate_revenue --arg range_days=30
silk tools call list_appointments --json-args '{"date_from":"2026-11-01","date_to":"2026-11-07"}'

# każde polecenie z --json zwraca surowy JSON (do jq i skryptów)
silk kpi --last 7d --json
  • Skróty (revenue, kpi, appointments, billing) tylko odczytują dane.
  • silk tools call wykonuje dowolne narzędzie, na które pozwala zakres klucza. Narzędzia zmieniające dane pytają o potwierdzenie (albo przyjmują --yes).
  • Dane klientek wracają jako tokeny zamiast imion i telefonów.

MCP

Salon w asystencie AI (MCP)

Serwer MCP daje asystentom AI (Claude, ChatGPT i innym klientom MCP) te same narzędzia salonu co CLI. Autoryzacja, izolacja salonów, kontrola ról i anonimizacja danych klientek zostają po stronie SilkCRM.

Zdalny serwer (HTTP)

Adres: https://app.silkcrm.net/mcp. Serwer przyjmuje logowanie OAuth kontem SilkCRM (tak łączy się konektor dodany w claude.ai) albo klucz API w nagłówku Authorization: Bearer silk_live_…. W claude.ai dodaj własny konektor z tym adresem i zaloguj się kontem salonu. Podłączonych asystentów zobaczysz w aplikacji: Ustawienia → Zaawansowane → Integracje → „Połączenia AI”, gdzie zmienisz ich zakres albo je odłączysz.

Lokalny serwer (stdio)

Pakiet @silkcrm/mcp uruchamia serwer na Twoim komputerze (Node.js 18 lub nowszy) z kluczem API w zmiennej SILK_API_KEY. Claude Desktop: Ustawienia → Developer → Edit Config.

claude_desktop_config.jsonJSON
{
  "mcpServers": {
    "silkcrm": {
      "command": "npx",
      "args": ["-y", "@silkcrm/mcp"],
      "env": {
        "SILK_API_KEY": "silk_live_TWOJ_KLUCZ"
      }
    }
  }
}
Claude CodeTerminal
# lokalnie (stdio), klucz API ze zmiennej środowiskowej
claude mcp add silkcrm -e SILK_API_KEY=$SILK_API_KEY -- npx -y @silkcrm/mcp

# zdalnie (HTTP), ten sam klucz API w nagłówku
claude mcp add --transport http silkcrm https://app.silkcrm.net/mcp \
  --header "Authorization: Bearer $SILK_API_KEY"

Instrukcja krok po kroku, którą może przeprowadzić sam asystent: silkcrm.net/silkcrm-mcp.md.

Wersje

Wersje i zmiany

Wersja stoi w ścieżce: /api/rest/v1. Zmiany zgodne wstecz (nowa operacja, nowe pole w odpowiedzi, nowy parametr opcjonalny) wchodzą bez zmiany wersji, więc Twój kod powinien ignorować pola, których nie zna. Zmiana niezgodna wstecz oznacza nową wersję w ścieżce.

  1. 1.0.0 2026-11-06

    • Pierwsze wydanie REST API v1 dla sklepów internetowych salonów.
    • Katalog: salony, usługi, specjalistki, szablony karnetów.
    • Karta klientki po telefonie lub e-mailu z zamówienia, ze zgodami marketingowymi (tylko nadanie).
    • Vouchery kwotowe i karnety: wydanie, odczyt, unieważnienie przy zwrocie w sklepie.
    • Stan zamówienia sklepu w Silku.
    • Idempotencja zapisów, tryb próby Silk-Dry-Run, jednolity kształt błędów.

Pytania o integrację: tech@silkcrm.net. Do zgłoszenia dołącz request_id z odpowiedzi i prefiks klucza, nigdy cały klucz.

Używamy cookies

Niezbędne pliki cookie pozwalają nam utrzymać Twoją sesję. Statystyczne i marketingowe pomagają nam ulepszać produkt i mierzyć skuteczność kampanii. Możesz zarządzać preferencjami w każdej chwili.