API-integraatio
Käytännön opas kopioitavine esimerkkeineen Gibbondin GraphQL-API:n integrointiin — taustajärjestelmästä, mobiili- tai verkkosovelluksesta tai toisesta myyntikanavasta. Koko skeema löytyy API-viitteestä.
Tällä sivulla
Pro-tilaus. Luo API-avain Gibbondin hallinnan API-avaimet-sivulla ja säilytä se palvelimen ympäristömuuttujassa. Alla olevissa esimerkeissä oletetaan, että GIBBOND_API_KEY sisältää WRITE-avaimen.
Näin osat liittyvät toisiinsa
Tunnistetietoja on kahdenlaisia, ja oikean valitseminen on tärkeää:
- API-avain (
glk_live_…) — tunnistaa taustajärjestelmäsi. Sillä voi lukea ja muuttaa kaikkien jäsenten tietoja, joten sitä säilytetään vain palvelimellasi. Käytä sitä palvelinten väliseen viestintään ja asiakastokenien luomiseen. - Asiakastoken — lyhytikäinen tunnistetieto, joka on rajattu yhteen asiakkaaseen. Taustajärjestelmäsi luo sen API-avaimella ja välittää sen asiakasohjelmalle (selaimelle tai sovellukselle). Asiakasohjelma voi tarkastella tietoja ja tehdä toimintoja vain kyseiselle asiakkaalle, joten tokenin voi välittää turvallisesti laitteelle.
Valitse integraatiotapa
| Rakennat… | Käytä | Siirry kohtaan |
|---|---|---|
| Taustajärjestelmän tehtävää, ERP-synkronointia tai headless-taustapalvelua | API-avainta suoraan | Taustajärjestelmästäsi |
| Mobiili- tai yhden sivun sovellusta, joka näyttää jäsenelle hänen pisteensä | API-avain palvelimella → asiakastoken laitteella | Sovelluksessa |
| Kassajärjestelmää, markkinapaikkaa tai headless-kassaa, jossa asiakkaat ansaitsevat pisteitä | API-avainta, awardPointsForOrder | Toisesta kanavasta |
Pyyntöjen apufunktio
Kaikilla kutsuilla on sama muoto, joten kokoa ne yhteen apufunktioon. Tämä Node-esimerkki käyttää sisäänrakennettua fetch-funktiota (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;
} Tapa 1 — taustajärjestelmästäsi (palvelinten välillä)
WRITE-avaimella voit tehdä toimintoja kaikille kauppasi jäsenille. Liitä asiakas ohjelmaan, lue hänen tietonsa ja myönnä pisteitä:
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,
); Negatiivinen määrä kutsussa awardPoints ja kutsut clawbackPoints vaativat ADMIN-avaimen — käytä näihin työnkulkuihin erillisiä, tarkasti suojattuja tunnistetietoja.
Tapa 2 — mobiili- tai verkkosovelluksessa
Älä koskaan sijoita API-avainta sovellukseen. Luo sen sijaan omalle palvelimellesi pieni päätepiste, joka luo asiakastokenin kirjautuneelle käyttäjälle, ja anna sovelluksen kutsua Gibbondia suoraan tällä tokenilla.
Mistä asiakkaan GID saadaan?
Asiakastoken sidotaan siihen GID-tunnukseen, jonka välität kutsulle mintCustomerToken — vastaat siis siitä, että luot tokenin oikealle asiakkaalle. Gibbond todentaa taustajärjestelmäsi API-avaimella, mutta ei todenna loppuasiakasta. Ennen tokenin luomista palvelimesi on jo tiedettävä luotettavasti, mikä Shopify-asiakas on kirjautunut sisään. Tämä voidaan selvittää kolmella tavalla, suositusjärjestyksessä:
| Miten sovelluksesi kirjaa asiakkaan sisään | Mistä GID saadaan |
|---|---|
| Shopify Customer Account API (suositeltu) | Kirjaa asiakas sisään Shopifyn OAuth-pohjaisella Customer Account API -rajapinnalla. Taustajärjestelmäsi käyttää saatua tokenia varmennetun asiakkaan hakemiseen ja lukee hänen GID-tunnuksensa. Shopify allekirjoittaa henkilöllisyyden koko ketjun läpi. |
| Shopifyyn sisäänrakennettu käyttöliittymä | Jos toiminto suoritetaan Shopifyssa (teeman sovellusupotuksessa tai asiakastilin käyttöliittymälaajennuksessa), Shopify antaa jo allekirjoitetun henkilöllisyyden — sovellusvälityspalvelimen logged_in_customer_id-arvon tai asiakastilin istuntotokenin sub-kentän. Lue se palvelimella ja käytä kyseistä GID-tunnusta. |
| Oma kirjautumisesi | Omia käyttäjätilejä käyttävä kanava (mukautettu sovellus tai kassajärjestelmä) yhdistää käyttäjän Shopify-asiakkaan GID-tunnukseen asiakkaan luonnin yhteydessä tallentamasi vastaavuuden avulla. Vastaat yhteyden oikeellisuudesta, joten suojaa tämä reitti huolellisesti. |
Suositus: Customer Account API. Todenna headless-kaupan tai mobiilisovelluksen asiakkaat Shopifyn Customer Account API -rajapinnalla ja hae GID Shopifyn varmennetusta tokenista. Näin koko ketju — asiakas → Shopifyn varmentama henkilöllisyys → taustajärjestelmäsi → luotu asiakastoken — on lähtökohtaisesti luotettava, eikä sinun tarvitse suojata erillistä GID-vastaavuutta. Tämä tarkistus kuuluu alla olevaan requireAuth-väliohjelmistoon.
Jos käyttöliittymäsi toimii jo Shopifyn istunnon sisällä (teema-, kassa- tai asiakastililohkona), et yleensä tarvitse tätä API:a — verkkokaupan sovelluslohkot ja asiakastili-integraatio varmentavat Shopify-henkilöllisyyden puolestasi. Käytä asiakastokeneita tämän yhteyden ulkopuolella.
Palvelimellasi
Oma todennuksesi kertoo, mikä Shopify-asiakas on kirjautunut sisään (hänen GID-tunnuksensa). Luo hänelle 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,
});
}); Sovelluksessa
Hae token palvelimeltasi ja kutsu sitten Gibbondia suoraan. Kysely me kohdistuu tokenin asiakkaaseen — id-tunnusta ei tarvita:
// 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); Palkintojen lunastaminen sovelluksesta
Asiakastokenilla voi lunastaa palkinnon vain omalle asiakkaalleen — laitteelle ei tarvita kauppiaan avainta. Mutaatio palauttaa kertakäyttöisen alennuskoodin, jota voi käyttää kassalla:
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); Tokenit ovat oletuksena voimassa 15 minuuttia (voit asettaa ttlSeconds-arvon enintään 24 tuntiin). Jos kutsu palauttaa UNAUTHENTICATED, kutsu /loyalty/session uudelleen saadaksesi uuden tokenin ja yritä uudelleen.
Tapa 3 — ansaitse pisteitä toisesta myyntikanavasta
Kun tilaus tehdään muualla kuin Shopify-kassallasi — kassajärjestelmässä, markkinapaikassa tai headless-kaupassa — ilmoita se kutsulla awardPointsForOrder. Gibbond käyttää jäsenen tasokerrointa, aktiivisia Boosts-kampanjoita ja välitavoitteita aivan kuten Shopify-tilauksessa. Kutsu on idempotentti orderId-tunnuksen suhteen, joten sen voi toistaa turvallisesti:
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,
); Jokaisella tilausrivillä on valinnainen productId, valinnaiset collectionIds ja pakollinen lineTotal — tuote- ja kokoelmakohtaiset Boosts-kampanjat sekä poissulkemiset toimivat siis kuten Shopify-tilauksissa. Vahvista pisteet myöhemmin (esim. tilauksen käsittelyn jälkeen) kutsulla confirmPoints(customerId, orderId); peru pisteet hyvityksen yhteydessä kutsumalla clawbackPoints ADMIN-avaimella.
Virheet, uudelleenyritykset ja idempotenssi
- Koodit. Virheet palautetaan GraphQL-taulukossa
errors; lueerrors[0].extensions.code—UNAUTHENTICATED(401),FORBIDDEN(403, väärä käyttöoikeusalue),RATE_LIMITED(429),BAD_USER_INPUT(400),NOT_FOUND(404). - Pyyntörajoitukset. 600 pyyntöä minuutissa kutakin tunnistetietoa kohden. Kun saat vastauksen
429, odota otsakkeessaRetry-Afterilmoitettu sekuntimäärä ja yritä sitten uudelleen. - Idempotenssi. Välitä
idempotencyKeykutsulleawardPointsja pysyväorderIdkutsulleawardPointsForOrder. Samaa avainta tai tilausta ei koskaan sovelleta kahdesti — voit siis yrittää verkkovirheiden jälkeen uudelleen. - Tokenin vanheneminen. Jos asiakastoken palauttaa
UNAUTHENTICATED, luo uusi token ja yritä uudelleen.
Turvallisuuden tarkistuslista
- Säilytä API-avaimia vain palvelimen salaisuuksina — älä koskaan sovelluspaketeissa, selainkoodissa tai versionhallinnassa.
- Käytä asiakastokenia kaikessa laitteella suoritettavassa toiminnassa; älä koskaan API-avainta.
- Anna kullekin integraatiolle pienin tarvittava käyttöoikeusalue (
READ-avain koontinäyttöihin,WRITEpisteiden ansaitsemiseen ja lunastamiseen,ADMINvain hyvityksiin ja korjauksiin). - Vaihda avain hallinnassa heti, jos se on voinut vuotaa — mitätöinti tulee voimaan välittömästi.
- Luo asiakastokenit mahdollisimman lyhyellä käytännöllisellä
ttlSeconds-arvolla.
Koko luettelo tyypeistä, kyselyistä, mutaatioista ja kentistä löytyy API-viitteestä.