Integracja - Własny esklep
Wprowadzenie#
Twój sklep internetowy, Twoje zasady – jedna platforma do obsługi klientów!
Nie korzystasz z jednej z popularnych platform e-commerce? A może Twój sklep działa na autorskim oprogramowaniu? Zintegruj go z Thulium i zapewnij konsultantom wygodny dostęp do informacji o zamówieniach, bez konieczności przełączania się między systemami.
Dzięki integracji Własny esklep możesz połączyć Thulium z dowolnym sklepem internetowym udostępniającym odpowiednie API. Konsultanci zyskują dostęp do historii zamówień, ich statusów i szczegółów zakupów bezpośrednio podczas obsługi klienta.
Mniej przełączania między systemami, szybsze odpowiedzi i pełniejszy kontekst każdej rozmowy.
Zakres integracji#
Połączenie własnego sklepu internetowego z Thulium pozwala konsultantom szybciej docierać do informacji zakupowych i sprawniej obsługiwać klientów, niezależnie od kanału kontaktu.
- Historia zamówień zawsze pod ręką – sprawdzaj zamówienia klienta wraz ze statusami, datami, kosztami, zakupionymi produktami i adresami dostawy bezpośrednio w Thulium.
- Ostatnie zamówienie w zasięgu wzroku – szybko uzyskaj kontekst ostatnich zakupów klienta, aby sprawniej odpowiadać na pytania dotyczące realizacji zamówienia.
- Szybki dostęp do szczegółów w sklepie – przechodź bezpośrednio do wybranego zamówienia w panelu sklepu, bez konieczności jego ręcznego wyszukiwania.
- Wiele sklepów w jednym miejscu – połącz z Thulium kilka sklepów internetowych, np. B2B i B2C, i wygodnie rozpoznawaj źródło poszczególnych zamówień.
Integracja jest przeznaczona dla sklepów, które mają własne oprogramowanie lub platformę bez gotowej integracji z Thulium. Jeśli Twoja platforma jest na liście integracji, wygodniej będzie użyć gotowej.
Krok po kroku#
- Przejdź do Administracja → Integracje i wybierz Własny esklep.
- W sekcji uwierzytelniania uzupełnij wymagane pola.
gdzie:
- Adres URL sklepu – adres Twojego sklepu, musi zaczynać się od
https://– login i hasło są przesyłane do sklepu, więc połączenie musi być szyfrowane.
Login – login do API sklepu.
Hasło – hasło do API sklepu.
- Kliknij przycisk uwierzytelnienia. Thulium połączy się ze sklepem i sprawdzi, czy odpowiada poprawnie.
- Uzupełnij pole Nazwa integracji, aby agenci mogli łatwo rozpoznać, z którego sklepu pochodzi zamówienie – szczególnie jeśli korzystasz z kilku sklepów. Następnie kliknij Zapisz i uruchom, aby zapisać ustawienia i aktywować integrację. Możesz ją również uruchomić później za pomocą suwaka aktywacji.
Jeśli zmienisz adres, login lub hasło po uwierzytelnieniu, integracja przestaje być oznaczona jako uwierzytelniona i trzeba uwierzytelnić ją ponownie.
🚀 Gotowe – od teraz zamówienia klientów pojawią się w Thulium.
Informacje o zamówieniach w Thulium#
Wszystkie najważniejsze informacje o zakupach klienta w jednym miejscu! Dzięki integracji konsultanci mogą sprawdzać szczegóły zamówień bezpośrednio w Thulium, zarówno z poziomu historii kontaktu, jak i podczas obsługi rozmowy.
Thulium wyszukuje zamówienia po adresie e-mail klienta. Jeśli klient nie ma zapisanego e-maila, system użyje jego numeru telefonu. Gdy klient nie ma ani e-maila, ani numeru telefonu, zamówień nie da się wyszukać i lista będzie pusta.
Dla każdego zamówienia dostępne są następujące informacje:
- numer zamówienia i jego status (dokładnie taki, jaki zwraca sklep),
- data zamówienia,
- koszt całkowity, koszt produktów i koszt dostawy,
- lista produktów z ilościami,
- adres dostawy (miasto, kod pocztowy, ulica, kraj),
- odnośnik do zamówienia w sklepie.
Dzięki temu konsultant ma pod ręką informacje potrzebne do sprawnej obsługi pytań o zamówienia, bez konieczności każdorazowego otwierania panelu sklepu.
Historia kontaktu:
Kanał kontaktu:
Wymagania wobec API#
Thulium wywołuje Twój sklep pod adresem podanym w polu Adres URL sklepu, przekazując login i hasło (według opisu twórców integracji: jako uwierzytelnianie HTTP Basic).
Rejestracja – POST /thulium/integrations/register
Thulium wysyła w treści JSON identyfikator integracji (id), nazwę klienta (client) i opcjonalnie redirectUrl. Odpowiedź sklepu decyduje o dalszym przebiegu:
- 200 lub 204 – rejestracja zakończona od razu, system sprawdza następnie, czy sklep poprawnie zwraca zamówienia.
- Inna odpowiedź – integracja zostanie oznaczona jako nieudana.
Zamówienia – GET /thulium/integrations/orders
Nagłówek X-Thulium-Integration-Id zawiera identyfikator integracji. Parametry: email lub phoneNumber, page (numeracja od 0), size oraz opcjonalnie sort. Sklep zwraca JSON:
orders– lista zamówień,page,size.- Każde zamówienie:
id,status,orderDate(czas UTC w formacie2026-01-31T12:00:00Z),totalCosts,productsCosts,shippingCosts(obiekty zamountjako tekst, np."12.50", icurrencyjako trzyliterowy kod, np.PLN),products(lista znameiquantity≥ 1),orderUrl(adres zamówienia w sklepie) orazshippingAddress(city,postcode,street,country). - Pola tekstowe nie mogą być puste.
Podczas uwierzytelniania Thulium pobiera jedno zamówienie bez filtrów, żeby sprawdzić format odpowiedzi – sklep musi więc obsłużyć zapytanie bez email i phoneNumber.
Specyfikacja API#
openapi: 3.1.0
info:
title: Thulium E-commerce Integration API
version: 1.2.0
summary: >-
Contract implemented by a partner shop so that Thulium can register an integration
and read orders from it.
description: |
This specification describes **two endpoints your shop implements** so that Thulium can
connect to it, plus **one callback Thulium exposes** for you to call back when a client
finishes configuration on your side.
## What you need to build
| Endpoint | Purpose |
|---|---|
| `POST /thulium/integrations/register` | Register a new integration for one Thulium client |
| `GET /thulium/integrations/orders` | Return orders of a given customer |
## Fixed paths
The paths above are a **convention, not configuration**. Thulium asks the client only for
a base URL and always appends these exact paths to it. There is no way to point Thulium at
different paths, so expose them verbatim under whatever host you give the client.
Example: base URL `https://shop.example.com/api` means Thulium will call
`https://shop.example.com/api/thulium/integrations/register`.
## Authentication
Both endpoints are called server-to-server by Thulium with HTTP Basic authentication.
Only HTTPS is supported. Which credentials are sent depends on who runs the shop:
* **A shop serving a single Thulium client** — credentials the client entered in the
Thulium panel.
* **A partner serving many Thulium clients from one deployment** — one set of credentials
agreed between the partner and Thulium, the same for every client.
## Identifying the client
Every call to the orders endpoint carries the `X-Thulium-Integration-Id` header with the
`id` Thulium sent at registration. It stays the same for the lifetime of the integration,
including when the client registers it again.
A shop serving a single client may ignore it. A partner serving many clients uses it to pick
the installation: the credentials are shared, so the header is the only thing that says whose
orders to return. Bind the `id` to an installation on your configuration screen (the `302`
flow below), where the shop owner signs in, and answer `401` for an `id` you have not bound.
## Two registration flows
Your response to registration decides which flow applies:
* **`200 OK`** — nothing more is needed. Thulium immediately validates the connection by
fetching one order, and the integration becomes active.
* **`302 Found`** with a `Location` header — the client must finish configuration on a
screen you host. Thulium sends the client to that address, then waits for you to call
the callback. The `Location` host **must** match the host of the client's base URL;
a redirect to any other host is rejected.
A partner serving many clients **must** use the `302` flow — the configuration screen is the
only point at which it learns which installation the `id` belongs to.
contact:
name: Thulium
url: https://thulium.com
servers:
- url: "{baseUrl}"
description: Base URL the client configures in the Thulium panel.
variables:
baseUrl:
default: https://shop.example.com/api
security:
- basicAuth: []
tags:
- name: Registration
description: Connecting a Thulium client to your shop.
- name: Orders
description: Reading orders for an agent handling a conversation.
paths:
/thulium/integrations/register:
post:
tags: [Registration]
operationId: registerIntegration
summary: Register a new integration
description: |
Called once, when a Thulium client connects your shop.
Respond with `200 OK` if there is nothing for the client to do, or with `302 Found`
and a `Location` header if the client has to complete configuration on your side.
If you serve many clients, always respond with `302` and bind `id` to the installation
on that screen.
The same `id` may arrive again when the client retries a failed or expired registration.
Replace the previous binding rather than rejecting it.
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/RegistrationRequest"
responses:
"204":
description: |
Registration complete — nothing more is required from the client.
"302":
description: |
The client must finish configuration on a screen you host. Thulium hands `Location`
to its own UI, which sends the client there, and then waits for the callback.
Only the `Location` header is read — a response body, if you send one, is ignored.
`302` is the canonical response, but any `3xx` carrying `Location` is treated the
same way. A `3xx` without `Location` fails the registration.
headers:
Location:
required: true
description: |
Absolute or relative address of your configuration screen. Must be `https`,
and its host must match the host of the client's base URL. A relative
reference is resolved against the base URL.
schema:
type: string
format: uri-reference
examples:
- https://shop.example.com/setup?ticket=a1b2c3
"400":
description: The request was malformed.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"401":
description: Authentication failed.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"500":
description: Registration failed on your side.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
callbacks:
configurationCompleted:
"{$request.body#/redirectUrl}":
post:
operationId: notifyConfigurationCompleted
summary: Tell Thulium the client finished configuration
description: |
Call this **only** in the `302` flow, once the client has completed
configuration on your screen. Send it **server-to-server** — do not redirect
the client's browser here, because the client may have closed the window
by then.
The address is the exact `redirectUrl` you received during registration.
It already carries an opaque one-time token in its query string; send it back
unchanged and do not try to interpret, store or reuse it.
The token is valid for **15 minutes** and works exactly once. Thulium verifies
the result independently by fetching one order from your orders endpoint before
activating the integration.
security: []
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/ConfigurationResult"
responses:
"200":
description: >-
Confirmation accepted and the integration is now active.
"400":
description: >-
The token is not recognised (`invalid-state`). Do not retry.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"409":
description: >-
The token has already been used (`state-already-used`). The integration
was confirmed earlier. Do not retry.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"410":
description: >-
The token expired (`state-expired`). More than 15 minutes passed and the client
has to start again from the Thulium panel. Do not retry.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"422":
description: >-
Confirmation accepted, but the follow-up check against your orders endpoint
returned data that does not match this specification (`schema-invalid`).
The response body says which field is wrong.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
/thulium/integrations/orders:
get:
tags: [Orders]
operationId: getOrders
summary: Return orders of a given customer
description: |
Returns the orders of a single customer of your shop — the person an agent is currently
talking to. Thulium calls it during a conversation, and once right after registration
to validate the connection.
Identify the customer by `phoneNumber` or `email` — at least one is always sent.
Return the newest orders first. Thulium fetches a single most-recent order by
requesting `size=1`, so the same endpoint serves both the list and the "last order" case.
If the customer is unknown, return `200` with an empty `orders` array — not `404`.
If the integration is unknown — an `X-Thulium-Integration-Id` you have not bound —
return `401`. The two must stay distinct: an empty list tells the agent the customer has
no orders, while `401` tells Thulium the integration itself is broken.
parameters:
- name: X-Thulium-Integration-Id
in: header
required: true
description: |
The `id` Thulium sent at registration, identifying which client's installation the
request is for. Always sent, including on the validation call right after registration.
A shop serving a single client may ignore it.
schema:
type: string
format: uuid
examples: ["7f3a1c62-9e41-4d3b-8a17-0d5b2f9c4e11"]
- name: phoneNumber
in: query
required: false
description: Customer's phone number, as stored in Thulium. Sent together with or instead of `email`.
schema:
type: string
examples: ["+48123456789"]
- name: email
in: query
required: false
description: Customer's e-mail address. Sent together with or instead of `phoneNumber`.
schema:
type: string
format: email
examples: ["jane.doe@example.com"]
- name: sort
in: query
required: false
description: |
Sorting instructions as `field,direction` pairs. Repeat the parameter for multiple
keys; they apply in the order given. Direction is `asc` or `desc`, defaulting to `asc`.
Ignore fields you cannot sort by rather than failing the request.
style: form
explode: true
schema:
type: array
items:
type: string
pattern: '^[a-zA-Z]+(,(asc|desc))?$'
examples:
- ["orderDate,desc"]
- ["orderDate,desc", "id,asc"]
- name: page
in: query
required: false
description: Zero-based page index.
schema:
type: integer
minimum: 0
default: 0
- name: size
in: query
required: false
description: Page size. Thulium sends `size=1` when it only needs the most recent order.
schema:
type: integer
minimum: 1
default: 20
responses:
"200":
description: Orders for the given customer. An unknown customer yields an empty array.
content:
application/json:
schema:
$ref: "#/components/schemas/Orders"
"400":
description: The request was malformed.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"401":
description: >-
Authentication failed, or `X-Thulium-Integration-Id` is not bound to any installation.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
"500":
description: The orders could not be read on your side.
content:
application/problem+json:
schema:
$ref: "#/components/schemas/ProblemDetails"
components:
securitySchemes:
basicAuth:
type: http
scheme: basic
description: >-
Sent on every call to both endpoints. HTTPS only. Either the credentials the client
entered in the Thulium panel, or — for a partner serving many clients — one set agreed
with Thulium and shared by all of them. Shared credentials authenticate Thulium, not the
client; the client is identified by `X-Thulium-Integration-Id`.
schemas:
RegistrationRequest:
type: object
required: [id, client]
properties:
id:
type: string
format: uuid
description: >-
Thulium's identifier for this integration. Sent again in `X-Thulium-Integration-Id`
on every call to the orders endpoint. If you serve many clients, bind it to the
installation on your configuration screen; otherwise use it only to correlate your
own records with Thulium's.
examples: ["7f3a1c62-9e41-4d3b-8a17-0d5b2f9c4e11"]
client:
type: string
description: Identifier of the Thulium client the integration belongs to.
examples: ["acme"]
redirectUrl:
type: string
format: uri
description: |
Address to call once the client finishes configuration on your side.
Present only when the client's configuration expects that step; absent when
registration is meant to complete immediately.
Treat it as opaque: it already contains a one-time token. Use it verbatim,
do not append to it and do not store it beyond this registration.
examples:
- https://app.thulium.com/api/custom-ecommerce/callback?state=b0Fh2Xq9
ConfigurationResult:
type: object
required: [result]
properties:
result:
type: string
enum: [ok, error]
description: >-
`ok` when the client completed configuration successfully, `error` when it failed
or the client abandoned it. Thulium verifies `ok` independently before activating
the integration.
message:
type: string
description: >-
Optional human-readable detail, shown to the Thulium client when `result` is
`error`. Do not put secrets here.
examples: ["The shop has no active API plan"]
Orders:
type: object
required: [orders, page, size]
properties:
orders:
type: array
description: Orders on this page, newest first. Empty when the customer is unknown.
items:
$ref: "#/components/schemas/Order"
page:
type: integer
minimum: 0
description: Zero-based index of the returned page.
size:
type: integer
minimum: 1
description: Page size that was applied.
Order:
type: object
required: [id, status, orderDate, totalCosts, products]
properties:
id:
type: string
description: Order identifier as the customer sees it.
examples: ["ORD-2026-00123"]
status:
type: string
description: >-
Order status. The set of allowed values is still being agreed — until it is fixed,
send your own value and Thulium will display it as-is.
examples: ["SHIPPED"]
orderDate:
type: string
format: date-time
description: When the order was placed, with a timezone offset.
examples: ["2026-08-11T14:32:05+02:00"]
totalCosts:
allOf:
- $ref: "#/components/schemas/Money"
description: Total amount paid by the customer, including shipping.
productsCosts:
allOf:
- $ref: "#/components/schemas/Money"
description: Amount for the products alone, excluding shipping. Optional.
shippingCosts:
allOf:
- $ref: "#/components/schemas/Money"
description: Shipping amount. Optional.
products:
type: array
description: Line items on the order.
items:
$ref: "#/components/schemas/Product"
orderUrl:
type: string
format: uri
description: >-
Address of the order in your own system, opened by the agent in a new tab. Optional.
examples: ["https://shop.example.com/admin/orders/ORD-2026-00123"]
shippingAddress:
$ref: "#/components/schemas/Address"
customer:
$ref: "#/components/schemas/Customer"
paymentMethod:
type: string
pattern: '\S'
description: >-
Payment method as shown to the customer. Optional, but must not be blank when sent.
Thulium may read it out to the caller, so send a human-readable name rather than an
internal code.
examples: ["BLIK"]
deliveryMethod:
type: string
pattern: '\S'
description: >-
Delivery method as shown to the customer. Optional, but must not be blank when sent.
Send a human-readable name rather than an internal code.
examples: ["InPost Paczkomat"]
trackingNumber:
type: string
pattern: '\S'
description: >-
Shipment tracking number assigned by the carrier. Optional, but must not be blank
when sent.
examples: ["602677016330421016183457"]
Money:
type: object
required: [amount, currency]
description: |
Monetary amount, always sent as a pair of value and currency.
`amount` is a **decimal string**, not a JSON number. Numbers in JSON are read as binary
floating point by most parsers, which turns `92.12` into something slightly off and makes
sums drift. A string keeps the value exact all the way through.
properties:
amount:
type: string
pattern: '^\d+(\.\d{1,4})?$'
description: >-
Non-negative decimal value, dot as the separator. No thousands separators, no
currency symbol, no leading plus. The number of fraction digits should match the
currency's minor unit — two for `PLN` or `EUR`, none for `JPY`.
examples: ["92.12"]
currency:
type: string
pattern: '^[A-Z]{3}$'
description: Currency as an ISO 4217 alpha-3 code, uppercase.
examples: ["PLN"]
Product:
type: object
required: [name, quantity]
properties:
name:
type: string
description: Product name as shown to the customer.
examples: ["Thermal mug 500 ml"]
quantity:
type: integer
minimum: 1
description: Number of units ordered.
examples: [2]
Address:
type: object
description: Shipping address. Optional as a whole; send what you have.
properties:
street:
type: string
examples: ["12 Market Street"]
city:
type: string
examples: ["Warsaw"]
postcode:
type: string
examples: ["00-001"]
country:
type: string
description: Country name or ISO 3166-1 alpha-2 code.
examples: ["PL"]
Customer:
type: object
description: >-
Person who placed the order. Optional as a whole; send what you have. A field you send
must not be blank.
properties:
firstName:
type: string
pattern: '\S'
examples: ["Jane"]
lastName:
type: string
pattern: '\S'
examples: ["Doe"]
ProblemDetails:
type: object
description: |
Error payload as defined by [RFC 9457](https://www.rfc-editor.org/rfc/rfc9457),
served with media type `application/problem+json`.
Branch on `type` — it is the stable, machine-readable identifier. `title` and `detail`
are meant for humans and may be reworded without notice. Additional extension members
may appear, so ignore anything you do not recognise rather than failing to parse.
properties:
type:
type: string
format: uri
default: "about:blank"
description: >-
URI identifying the problem type. Dereferenceable, but treat it as an identifier
rather than a link.
examples: ["https://thulium.com/problems/state-expired"]
title:
type: string
description: Short, human-readable summary of the problem type.
examples: ["Confirmation token expired"]
status:
type: integer
description: HTTP status code, repeated for convenience.
examples: [410]
detail:
type: string
description: Human-readable explanation specific to this occurrence.
examples: ["The token expired 4 minutes ago. Ask the client to start again."]
instance:
type: string
format: uri-reference
description: URI identifying this specific occurrence, useful when reporting issues.
examples: ["/api/custom-ecommerce/callback/errors/9f21c4"]
Twój sklep, Twoi klienci, wszystkie informacje w jednym miejscu. Połącz własny esklep z Thulium i zapewnij konsultantom dostęp do danych zakupowych, które pomagają szybciej rozwiązywać problemy i budować lepsze doświadczenia klientów.