Integracja API
Praktyczny przewodnik z przykładami do skopiowania, który pokazuje integrację z API GraphQL Gibbond — z systemu zaplecza, aplikacji mobilnej lub internetowej albo innego kanału sprzedaży. Pełny schemat znajdziesz w referencji API.
Na tej stronie
Plan Pro. Utwórz klucz API na stronie Klucze API w panelu administracyjnym Gibbond, a następnie przechowuj go w zmiennej środowiskowej serwera. Poniższe przykłady zakładają, że GIBBOND_API_KEY zawiera klucz z zakresem WRITE.
Jak to działa
Są dwa rodzaje danych uwierzytelniających — najważniejsze jest, by wybrać właściwy:
- Klucz API (
glk_live_…) — identyfikuje Twoje zaplecze. Umożliwia odczyt i zapis danych wszystkich członków, dlatego należy przechowywać go wyłącznie na serwerze. Używaj go do komunikacji między serwerami i tworzenia tokenów klienta. - Token klienta — krótkotrwałe dane uwierzytelniające ograniczone do jednego klienta. Twoje zaplecze tworzy go za pomocą klucza API i przekazuje klientowi (przeglądarce lub aplikacji). Klient może wtedy wyświetlać dane i wykonywać działania tylko na koncie tej osoby, więc token można bezpiecznie przekazać na urządzenie.
Wybierz odpowiedni sposób integracji
| Tworzysz… | Użyj | Przejdź do |
|---|---|---|
| Proces zaplecza, synchronizację z systemem ERP lub backend headless | Bezpośrednio klucza API | Z backendu |
| Aplikację mobilną lub jednostronicową aplikację pokazującą członkowi jego punkty | Klucza API na serwerze → tokenu klienta na urządzeniu | W aplikacji |
| System POS, marketplace lub checkout headless, w którym klienci mają zdobywać punkty | Klucz API, awardPointsForOrder | Z innego kanału |
Funkcja pomocnicza do żądań
Każde wywołanie ma ten sam format, dlatego warto opakować je w funkcję. Poniższy przykład dla Node.js korzysta z wbudowanego fetch (Node 18+):
// gibbond.js
const ENDPOINT = "https://app.gibbond.com/api/v1/graphql";
export async function gibbond(query, variables, token) {
const res = await fetch(ENDPOINT, {
method: "POST",
headers: {
"Authorization": "Bearer " + token,
"Content-Type": "application/json",
},
body: JSON.stringify({ query, variables }),
});
if (res.status === 429) {
const retryAfter = Number(res.headers.get("Retry-After") || 1);
const err = new Error("Rate limited");
err.retryAfter = retryAfter;
throw err;
}
const json = await res.json();
if (json.errors && json.errors.length) {
const code = json.errors[0].extensions && json.errors[0].extensions.code;
throw new Error(code + ": " + json.errors[0].message);
}
return json.data;
} Sposób 1 — z backendu (komunikacja między serwerami)
Za pomocą klucza WRITE możesz wykonywać operacje na każdym członku swojego sklepu. Zapisz klienta do programu lojalnościowego, odczytaj jego dane i przyznaj mu punkty:
import { gibbond } from "./gibbond.js";
const KEY = process.env.GIBBOND_API_KEY;
const id = "gid://shopify/Customer/123456789";
// Enroll a customer (idempotent — safe to call again).
await gibbond(
"mutation($id: ID!, $email: String) { enrollCustomer(customerId: $id, email: $email) { ok customer { enrolled } } }",
{ id, email: "ada@example.com" },
KEY,
);
// Read their balance and tier.
const { customer } = await gibbond(
"query($id: ID!) { customer(id: $id) { balance pending lifetime tier { name multiplier } } }",
{ id },
KEY,
);
// Grant points. idempotencyKey makes retries safe — the same key never double-applies.
await gibbond(
"mutation($id: ID!, $pts: Int!, $k: String) { awardPoints(customerId: $id, points: $pts, reason: \"Newsletter signup\", idempotencyKey: $k) { ok pointsApplied balance { balance } } }",
{ id, pts: 100, k: "newsletter-123456789" },
KEY,
); Ujemna wartość w mutacji awardPoints oraz wywołanie clawbackPoints wymagają klucza ADMIN — do tych operacji używaj osobnego, ściśle chronionego klucza.
Sposób 2 — w aplikacji mobilnej lub internetowej
Nigdy nie umieszczaj klucza API w aplikacji. Udostępnij na własnym serwerze niewielki punkt końcowy, który tworzy token klienta dla zalogowanego użytkownika, a następnie pozwól aplikacji komunikować się bezpośrednio z Gibbond za pomocą tego tokenu.
Skąd wziąć GID klienta?
Token klienta jest powiązany z GID przekazanym do mintCustomerToken — dlatego musisz utworzyć go dla właściwego klienta. Gibbond uwierzytelnia Twoje zaplecze (za pomocą klucza API), ale nie uwierzytelnia kupującego. Zanim utworzysz token, serwer musi już wiedzieć i mieć pewność, który klient Shopify jest zalogowany. Można to ustalić na trzy sposoby, uporządkowane według preferencji:
| Sposób logowania kupującego w aplikacji | Źródło GID |
|---|---|
| Shopify Customer Account API (zalecane) | Zaloguj kupującego przez oparty na OAuth mechanizm Shopify: Customer Account API. Backend wymienia otrzymany token na zweryfikowaną tożsamość klienta i odczytuje jego GID. Tożsamość jest weryfikowana przez Shopify na całej drodze. |
| Interfejs natywny dla Shopify | Jeśli interfejs działa wewnątrz Shopify (jako osadzenie aplikacji w motywie lub rozszerzenie UI konta klienta), Shopify udostępnia już podpisaną tożsamość — odczytaj ją z proxy aplikacji (logged_in_customer_id) lub pola sub tokenu sesji konta klienta. Odczytaj ją po stronie serwera i użyj tego GID. |
| Własny system logowania | W kanale z własnymi kontami (np. aplikacji niestandardowej lub systemie POS) przypisz użytkownika do GID klienta Shopify, korzystając z mapowania zapisanego podczas tworzenia konta. To Ty potwierdzasz to powiązanie, dlatego starannie zabezpiecz ten mechanizm. |
Zalecane: Customer Account API. W sklepie headless lub aplikacji mobilnej uwierzytelniaj kupujących za pomocą Customer Account API i pobieraj GID ze zweryfikowanego tokenu Shopify. Dzięki temu cały łańcuch — kupujący → tożsamość zweryfikowana przez Shopify → backend → utworzony token klienta — jest zaufany z założenia i nie musisz zabezpieczać własnego mapowania GID. Middleware requireAuth w przykładzie poniżej to właściwe miejsce na tę weryfikację.
Jeśli interfejs działa już wewnątrz sesji Shopify (jako blok motywu, checkoutu lub konta klienta), zwykle nie potrzebujesz tego API — bloki aplikacji w sklepie w motywie i integracja z kontem klienta weryfikują tożsamość Shopify za Ciebie. Korzystaj z tokenów klienta, gdy działasz poza takim środowiskiem.
Na serwerze
Własny mechanizm uwierzytelniania informuje, który klient Shopify jest zalogowany (jego GID). Utwórz dla niego token:
import express from "express";
import { gibbond } from "./gibbond.js";
const app = express();
// requireAuth is YOUR session middleware; it sets req.customerGid.
app.post("/loyalty/session", requireAuth, async (req, res) => {
const data = await gibbond(
"mutation($id: ID!) { mintCustomerToken(customerId: $id, ttlSeconds: 900) { token expiresAt } }",
{ id: req.customerGid },
process.env.GIBBOND_API_KEY, // WRITE key, server-side only
);
// Hand the app the token, when it expires, and the id it is bound to.
res.json({
token: data.mintCustomerToken.token,
expiresAt: data.mintCustomerToken.expiresAt,
customerId: req.customerGid,
});
}); W aplikacji
Pobierz token z serwera, a następnie wywołaj Gibbond bezpośrednio. Zapytanie me zwraca klienta przypisanego do tokenu, więc nie trzeba podawać identyfikatora:
// 1. Get a short-lived token from YOUR backend.
const session = await fetch("/loyalty/session", { method: "POST" }).then(r => r.json());
// 2. Call Gibbond with the customer token.
async function loyalty(query, variables) {
const res = await fetch("https://app.gibbond.com/api/v1/graphql", {
method: "POST",
headers: {
"Authorization": "Bearer " + session.token,
"Content-Type": "application/json",
},
body: JSON.stringify({ query, variables }),
});
return (await res.json()).data;
}
// Show the member their points, tier, and reward codes.
const { me } = await loyalty("{ me { name balance lifetime tier { name multiplier } } }");
const { activeCodes } = await loyalty(
"query($id: ID!) { activeCodes(customerId: $id) { code rewardName status expiresAt } }",
{ id: session.customerId },
);
renderRewardsScreen(me, activeCodes); Wymiana nagrody w aplikacji
Za pomocą tokenu klienta można wymienić nagrodę na własnym koncie — klucz sprzedawcy nie jest potrzebny na urządzeniu. Mutacja zwraca jednorazowy kod rabatowy do zastosowania przy kasie:
const { redeemReward } = await loyalty(
"mutation($id: ID!, $reward: ID!) { redeemReward(customerId: $id, rewardId: $reward) { ok code { code rewardName pointsSpent expiresAt } } }",
{ id: session.customerId, reward: "gid_or_reward_id_from_rewards_query" },
);
if (redeemReward.ok) applyDiscountCode(redeemReward.code.code); Domyślnie tokeny są ważne przez 15 minut (wartość ttlSeconds można zwiększyć do 24 godzin). Jeśli wywołanie zwróci błąd UNAUTHENTICATED, ponownie wywołaj /loyalty/session, aby uzyskać nowy token i ponowić żądanie.
Sposób 3 — naliczanie punktów w innym kanale sprzedaży
Gdy zamówienie zostanie złożone poza checkoutem Shopify — w systemie POS, marketplace lub sklepie headless — zgłoś je za pomocą awardPointsForOrder. Gibbond stosuje mnożnik poziomu członka, aktywne boosty i kamienie milowe tak samo jak przy zamówieniu Shopify. Operacja jest idempotentna względem orderId, więc można bezpiecznie ponawiać żądanie:
await gibbond(
`mutation($input: OrderInput!) {
awardPointsForOrder(input: $input) {
ok
pointsApplied
balance { balance lifetime }
}
}`,
{
input: {
orderId: "pos-2026-000123",
customerId: "gid://shopify/Customer/123456789",
customerEmail: "ada@example.com",
orderName: "POS #000123",
lineItems: [
{ productId: "gid://shopify/Product/55", collectionIds: ["gid://shopify/Collection/9"], lineTotal: 42.0 },
{ lineTotal: 8.5 },
],
},
},
process.env.GIBBOND_API_KEY,
); Każda pozycja zamówienia może zawierać opcjonalne pola productId i collectionIds oraz wymaganą wartość lineTotal — boosty i wykluczenia dla produktów oraz kolekcji działają tak samo jak przy zamówieniach Shopify. Aby później potwierdzić punkty (np. po realizacji zamówienia), wywołaj confirmPoints(customerId, orderId); aby cofnąć punkty po zwrocie środków, wywołaj clawbackPoints z kluczem ADMIN.
Błędy, ponowienia i idempotencja
- Kody. Błędy są zwracane w tablicy GraphQL
errors; odczytajerrors[0].extensions.code—UNAUTHENTICATED(401),FORBIDDEN(403, niewłaściwy zakres),RATE_LIMITED(429),BAD_USER_INPUT(400),NOT_FOUND(404). - Limity zapytań. 600 żądań na minutę dla każdych danych uwierzytelniających. Po otrzymaniu
429odczekaj liczbę sekund podaną w nagłówkuRetry-After, a następnie ponów żądanie. - Idempotencja. Przekaż klucz
idempotencyKeydo mutacjiawardPointsi stały identyfikatororderIddoawardPointsForOrder. Ponowne wysłanie tego samego klucza lub zamówienia nie spowoduje podwójnego naliczenia, więc można swobodnie ponawiać żądania po błędach sieci. - Wygaśnięcie tokenu. Błąd
UNAUTHENTICATEDdla tokenu klienta oznacza, że trzeba utworzyć nowy token i ponowić żądanie.
Zasady bezpieczeństwa
- Przechowuj klucze API wyłącznie w bezpiecznych zmiennych serwera — nigdy w pakiecie aplikacji, kodzie przeglądarkowym ani systemie kontroli wersji.
- Używaj tokenu klienta do operacji wykonywanych na urządzeniu; nigdy nie umieszczaj tam klucza API.
- Przyznawaj każdej integracji najniższy wymagany zakres (klucz
READdo paneli,WRITEdo naliczania i wymiany punktów, aADMINwyłącznie do zwrotów i korekt). - Wymień klucz w panelu administracyjnym, gdy tylko podejrzewasz jego wyciek — cofnięcie uprawnień działa natychmiast.
- Twórz tokeny klienta z możliwie najkrótszym czasem ważności
ttlSeconds.
Pełną listę typów, zapytań, mutacji i pól znajdziesz w referencji API.