API-integration
En praktisk guide med eksempler, du kan kopiere, til integration med Gibbonds GraphQL-API — fra et administrationssystem, en mobil- eller webapp eller en anden salgskanal. Se API-referencen for hele skemaet.
På denne side
Pro-abonnement. Opret en API-nøgle på siden API-nøgler i Gibbond-administrationen, og gem den i en miljøvariabel på serveren. Eksemplerne nedenfor forudsætter, at GIBBOND_API_KEY indeholder en WRITE-nøgle.
Sådan hænger delene sammen
Der findes to slags legitimationsoplysninger, og det er vigtigt at vælge den rigtige:
- API-nøgle (
glk_live_…) — identificerer din backend. Den kan læse og ændre alle medlemmers data og må derfor kun ligge på din server. Brug den til kommunikation mellem servere og til at udstede kundetokens. - Kundetoken — kortvarige legitimationsoplysninger begrænset til én kunde. Din backend udsteder tokenet med API-nøglen og sender det til en klient (browser eller app). Klienten kan kun se og udføre handlinger for den pågældende kunde, så tokenet kan sikkert sendes til enheden.
Vælg integrationsmønster
| Du bygger… | Brug | Gå til |
|---|---|---|
| En administrationsopgave, ERP-synkronisering eller headless-backend | API-nøglen direkte | Fra din backend |
| En mobilapp eller enkeltsideapp, der viser et medlem deres point | API-nøgle på serveren → kundetoken på enheden | I en app |
| Et kassesystem, en markedsplads eller en headless-checkout, hvor kunder skal optjene point | API-nøgle, awardPointsForOrder | Fra en anden kanal |
En hjælpefunktion til anmodninger
Alle kald har samme format, så saml dem i en hjælpefunktion. Dette Node-eksempel bruger den indbyggede 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;
} Mønster 1 — fra din backend (server til server)
Med en WRITE-nøgle kan du udføre handlinger for alle medlemmer i din butik. Tilmeld en kunde, læs deres data, og tildel point:
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,
); Et negativt beløb i awardPoints og kald til clawbackPoints kræver en ADMIN-nøgle — brug særskilte, omhyggeligt beskyttede legitimationsoplysninger til disse forløb.
Mønster 2 — i en mobil- eller webapp
Læg aldrig API-nøglen i en app. Opret i stedet et lille endepunkt på din egen server, der udsteder et kundetoken til den indloggede bruger, og lad appen kommunikere direkte med Gibbond via tokenet.
Hvor kommer kundens GID fra?
Et kundetoken er knyttet til det GID, du sender til mintCustomerToken — du har derfor ansvaret for at udstede det til den rigtige kunde. Gibbond godkender din backend via API-nøglen, men godkender ikke slutkunden. Før du udsteder tokenet, skal din server allerede vide og kunne stole på, hvilken Shopify-kunde der er logget ind. Det kan fastslås på tre måder, i prioriteret rækkefølge:
| Sådan logger appen kunden ind | Hvor GID kommer fra |
|---|---|
| Shopify Customer Account API (anbefalet) | Log kunden ind med Shopifys OAuth-baserede Customer Account API. Din backend bruger det resulterende token til at hente den verificerede kunde og læse deres GID. Identiteten er signeret af Shopify gennem hele forløbet. |
| En Shopify-integreret brugerflade | Hvis oplevelsen kører i Shopify (en appindlejring i temaet eller en UI-udvidelse til kundekonti), leverer Shopify allerede den signerede identitet — app-proxyens logged_in_customer_id eller feltet sub i et sessionstoken til kundekontoen. Læs værdien på serveren, og brug dette GID. |
| Dit eget login | En kanal med egne konti (en specialbygget app eller et kassesystem) knytter brugeren til et Shopify-kunde-GID via en tilknytning, du gemte, da kunden blev oprettet. Du står inde for tilknytningen, så beskyt denne adgangsvej omhyggeligt. |
Anbefalet: Customer Account API. Til en headless-butik eller mobilapp godkender du kunder med Shopifys Customer Account API og henter GID fra Shopifys verificerede token. Det gør hele kæden — kunde → Shopify-verificeret identitet → din backend → udstedt kundetoken — pålidelig fra starten, uden en GID-tilknytning, du selv skal beskytte. Denne kontrol hører hjemme i middleware-funktionen requireAuth nedenfor.
Hvis brugerfladen allerede kører inden for Shopifys session (en tema-, checkout- eller kundekontoblok), behøver du normalt ikke dette API — butikkens appblokke og integrationen til kundekonti verificerer Shopify-identiteten for dig. Brug kundetokens, når du arbejder uden for denne sammenhæng.
På din server
Din egen godkendelse fortæller dig, hvilken Shopify-kunde der er logget ind (deres GID). Udsted et token til kunden:
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,
});
}); I appen
Hent et token fra din server, og kald derefter Gibbond direkte. Forespørgslen me bruger den kunde, tokenet tilhører — intet id er nødvendigt:
// 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); Indløsning fra appen
Et kundetoken kan indløse en belønning for sin egen kunde — ingen forhandlernøgle behøves på enheden. Mutationen returnerer en engangsrabatkode, der kan bruges ved checkout:
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); Tokens er som standard gyldige i 15 minutter (indstil ttlSeconds op til 24 timer). Hvis et kald returnerer UNAUTHENTICATED, skal du kalde /loyalty/session igen for et nyt token og prøve igen.
Mønster 3 — optjen point fra en anden salgskanal
Når en ordre afgives uden for din Shopify-checkout — i et kassesystem, på en markedsplads eller i en headless-butik — indberetter du den med awardPointsForOrder. Gibbond anvender medlemmets niveaumultiplikator, aktive Boosts og milepæle, præcis som ved en Shopify-ordre. Kaldet er idempotent for orderId, så gentagne forsøg er sikre:
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,
); Hver ordrelinje indeholder et valgfrit productId, valgfrie collectionIds og et obligatorisk lineTotal — produkt- og kollektionsspecifikke Boosts og undtagelser fungerer derfor som ved Shopify-ordrer. For at bekræfte point senere (f.eks. efter klargøring) skal du kalde confirmPoints(customerId, orderId); for at tilbageføre dem ved en refusion skal du kalde clawbackPoints med en ADMIN-nøgle.
Fejl, gentagne forsøg og idempotens
- Koder. Fejl returneres i et GraphQL-array med navnet
errors; læserrors[0].extensions.code—UNAUTHENTICATED(401),FORBIDDEN(403, forkert adgangsomfang),RATE_LIMITED(429),BAD_USER_INPUT(400),NOT_FOUND(404). - Anmodningsgrænser. 600 anmodninger pr. minut pr. legitimationsoplysning. Ved
429skal du vente det antal sekunder, der står i headerenRetry-After, og derefter prøve igen. - Idempotens. Send en
idempotencyKeytilawardPointsog et stabiltorderIdtilawardPointsForOrder. Samme nøgle eller ordre anvendes aldrig dobbelt — du kan derfor prøve igen ved netværksfejl. - Tokenudløb. Hvis et kundetoken giver
UNAUTHENTICATED, skal du udstede et nyt og prøve igen.
Sikkerhedstjekliste
- Opbevar kun API-nøgler som hemmeligheder på serveren — aldrig i app-pakker, browserkode eller versionsstyring.
- Brug et kundetoken til alt, der kører på en enhed; aldrig en API-nøgle.
- Giv hver integration det mindst nødvendige adgangsomfang (en
READ-nøgle til dashboards,WRITEtil optjening og indløsning,ADMINkun til refusioner og rettelser). - Udskift nøglen i administrationen, så snart den kan være lækket — tilbagekaldelsen træder i kraft med det samme.
- Udsted kundetokens med den kortest praktiske
ttlSeconds.
Den komplette liste over typer, forespørgsler, mutationer og felter findes i API-referencen.