Integrazione API
Una guida pratica, con esempi da copiare, per integrare l’API GraphQL di Gibbond — da un servizio gestionale, un’app mobile o web oppure un altro canale di vendita. Consulta il riferimento API per lo schema completo.
In questa pagina
Piano Pro. Crea una chiave API nella pagina Chiavi API del pannello Gibbond e conservala in una variabile d’ambiente sul server. Gli esempi seguenti presuppongono che GIBBOND_API_KEY contenga una chiave WRITE.
Come si collegano i componenti
Esistono due tipi di credenziali: scegliere quella corretta è fondamentale.
- Chiave API (
glk_live_…) — identifica il tuo backend. Può leggere e modificare i dati di tutti gli iscritti, quindi deve rimanere esclusivamente sul tuo server. Usala per le comunicazioni tra server e per generare token cliente. - Token cliente — una credenziale di breve durata limitata a un solo cliente. Il tuo backend la genera con la chiave API e la passa a un client (browser o app). Il client può visualizzare i dati e agire soltanto per quel cliente, quindi il token può essere trasmesso al dispositivo in sicurezza.
Scegli il modello di integrazione
| Stai creando… | Usa | Vai a |
|---|---|---|
| Un’attività gestionale, una sincronizzazione ERP o un backend headless | La chiave API direttamente | Dal tuo backend |
| Un’app mobile o a pagina singola che mostra i punti a un iscritto | Chiave API sul server → token cliente sul dispositivo | Dentro un’app |
| Un POS, un marketplace o un checkout headless in cui accumulare punti | Chiave API, awardPointsForOrder | Da un altro canale |
Una funzione di supporto per le richieste
Tutte le chiamate hanno lo stesso formato: racchiudile in un’unica funzione. Questo esempio Node usa fetch integrato (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;
} Modello 1 — dal tuo backend (tra server)
Con una chiave WRITE puoi agire su qualsiasi iscritto del tuo negozio. Iscrivi un cliente al programma fedeltà, leggi i suoi dati e assegna punti:
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,
); Un importo negativo in awardPoints e le chiamate a clawbackPoints richiedono una chiave ADMIN — usa una credenziale separata e rigorosamente protetta per questi flussi.
Modello 2 — dentro un’app mobile o web
Non inserire mai la chiave API in un’app. Esponi invece un piccolo endpoint sul tuo server che genera un token cliente per l’utente autenticato e lascia che l’app comunichi direttamente con Gibbond tramite quel token.
Da dove proviene il GID del cliente?
Un token cliente è associato al GID che passi a mintCustomerToken — generarlo per il cliente corretto è quindi tua responsabilità. Gibbond autentica il tuo backend tramite la chiave API, ma non autentica l’acquirente finale. Prima di generare il token, il tuo server deve già sapere con certezza quale cliente Shopify ha effettuato l’accesso. Puoi stabilirlo in tre modi, in ordine di preferenza:
| Come la tua app autentica l’acquirente | Da dove proviene il GID |
|---|---|
| Shopify Customer Account API (consigliata) | Autentica l’acquirente tramite la Customer Account API di Shopify, basata su OAuth. Il tuo backend usa il token ottenuto per recuperare il cliente verificato e leggere il suo GID. L’identità è firmata da Shopify lungo tutta la catena. |
| Una superficie nativa Shopify | Se l’esperienza si svolge in Shopify (un’app incorporata nel tema o un’estensione dell’interfaccia dell’account cliente), Shopify fornisce già l’identità firmata — il valore logged_in_customer_id dell’app proxy oppure il campo sub del token di sessione dell’account cliente. Leggilo sul server e usa quel GID. |
| Il tuo sistema di accesso | Un canale con account propri (un’app personalizzata o un POS) associa il suo utente al GID di un cliente Shopify tramite una corrispondenza salvata alla creazione del cliente. Sei tu a garantire tale associazione, quindi proteggi attentamente questo percorso. |
Consigliata: la Customer Account API. Per uno storefront headless o un’app mobile, autentica gli acquirenti con la Customer Account API di Shopify e ricava il GID dal token verificato da Shopify. L’intera catena — acquirente → identità verificata da Shopify → tuo backend → token cliente generato — è così affidabile per costruzione, senza corrispondenze GID da proteggere. Questo controllo va eseguito nel middleware requireAuth riportato sotto.
Se la tua superficie opera già all’interno della sessione Shopify (un blocco del tema, del checkout o dell’account cliente), normalmente non ti serve questa API — i blocchi app dello storefront e l’integrazione dell’account cliente verificano l’identità Shopify per te. Usa i token cliente quando operi al di fuori di quel contesto.
Sul tuo server
Il tuo sistema di autenticazione identifica il cliente Shopify che ha effettuato l’accesso tramite il suo GID. Genera un token per quel cliente:
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,
});
}); Nell’app
Recupera un token dal tuo server, quindi chiama direttamente Gibbond. La query me identifica il cliente associato al token — non serve un id:
// 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); Riscattare premi dall’app
Un token cliente può riscattare un premio per il proprio cliente — nessuna chiave del merchant sul dispositivo. La mutation restituisce un codice sconto monouso da applicare al 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); I token durano 15 minuti per impostazione predefinita (puoi impostare ttlSeconds fino a 24 ore). Se una chiamata restituisce UNAUTHENTICATED, richiama /loyalty/session per ottenere un nuovo token e riprova.
Modello 3 — accumulare punti da un altro canale di vendita
Quando un ordine viene effettuato fuori dal checkout Shopify — da un POS, un marketplace o uno storefront headless — segnalalo con awardPointsForOrder. Gibbond applica il moltiplicatore del livello dell’iscritto, i Boosts attivi e i traguardi come per un ordine Shopify. La chiamata è idempotente rispetto a orderId, quindi puoi ripeterla in sicurezza:
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,
); Ogni riga d’ordine include un productId facoltativo, collectionIds facoltativi e un lineTotal obbligatorio — Boosts ed esclusioni per prodotto o collezione funzionano come per gli ordini Shopify. Per confermare i punti in seguito (ad esempio dopo l’evasione), chiama confirmPoints(customerId, orderId); per stornarli dopo un rimborso, chiama clawbackPoints con una chiave ADMIN.
Errori, tentativi e idempotenza
- Codici. Gli errori vengono restituiti nell’array GraphQL
errors; leggierrors[0].extensions.code—UNAUTHENTICATED(401),FORBIDDEN(403, ambito errato),RATE_LIMITED(429),BAD_USER_INPUT(400),NOT_FOUND(404). - Limiti delle richieste. 600 richieste al minuto per credenziale. In caso di
429, attendi i secondi indicati nell’headerRetry-Aftere riprova. - Idempotenza. Passa una
idempotencyKeyaawardPointse unorderIdstabile aawardPointsForOrder. La stessa chiave o lo stesso ordine non viene mai applicato due volte — puoi quindi riprovare dopo errori di rete. - Scadenza del token. Se un token cliente restituisce
UNAUTHENTICATED, generane uno nuovo e riprova.
Controlli di sicurezza
- Conserva le chiavi API esclusivamente nei segreti del server — mai nei pacchetti dell’app, nel codice del browser o nel controllo versione.
- Usa un token cliente per qualsiasi operazione sul dispositivo; mai una chiave API.
- Assegna a ogni integrazione l’ambito minimo necessario (chiave
READper le dashboard,WRITEper accumulare e riscattare punti,ADMINsolo per rimborsi e correzioni). - Sostituisci la chiave dal pannello non appena sospetti una compromissione — la revoca ha effetto immediato.
- Genera token cliente con il valore
ttlSecondspiù breve praticabile.
Per l’elenco completo di tipi, query, mutation e campi, consulta il riferimento API.