واجهة المورد

أبقِ كتالوجك ومخزونك وأسعارك على جراجي متوافقة مع نظامك (ERP أو نقاط البيع)، وتعامل مع طلبات مركز القطع منه. يمكن لجراجي أيضاً أن يرسل أحداثاً إلى نظامك (خطافات الويب)، أو أن يقرأ ملفاً من نظامك كل ليلة (سحب مجدول). يختار صاحب المحل هذا في جراجي: البيع ← نظامك.

ابدأ

  1. The shop owner chooses API push and creates a key. It is shown once: store it as a secret.
  2. Send it on every call: Authorization: Bearer gk_…. A key reaches its own shop only.
  3. Base address: https://nboenaiqwjwpbbaraeyt.supabase.co/functions/v1/supplier-api
  4. Try things against a test project first: ask Garagy for a key on the staging project, or use your local copy.

Limits: 120 calls a minute per key, 1,000 items and 2 MB per call. Money is in fils (1 BHD = 1000 fils); prices exclude VAT. Every call is logged and visible to the shop owner. OpenAPI description

أرسل المخزون والأسعار

Create or update items by SKU (your part number). Sending the same rows again changes nothing; each row is saved or reported on its own.

curl -X POST "https://nboenaiqwjwpbbaraeyt.supabase.co/functions/v1/supplier-api/v1/items" \
  -H "Authorization: Bearer $GARAGY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"items":[{"sku":"OF-1001","name":"Oil filter","brand":"Denso","oem_number":"04152-YZZA1","price_fils":2500,"wholesale_price_fils":2000,"quantity":12,"branch":"Main","list_on_marketplace":true,"fit":[{"make":"Toyota","model":"Camry","year_from":2015,"year_to":2020}]}]}'
{"received":1,"saved":1,"created":1,"updated":0,"errors":[]}

Fields: sku (required), name (required for a new item), name_ar, oem_number, brand, category, condition (new_oem, new_aftermarket, used, refurbished), price_fils, wholesale_price_fils, online_price_fils, list_on_marketplace, active, quantity (on hand at the branch, not a change), branch (name; main branch when left out), fit (replaces the list). Leave a field out to keep what Garagy has. Stock cannot go below what open orders hold.

Read back what Garagy holds, 500 at a time:

curl "https://nboenaiqwjwpbbaraeyt.supabase.co/functions/v1/supplier-api/v1/items?offset=0&limit=500" \
  -H "Authorization: Bearer $GARAGY_KEY"

الطلبات

curl "https://nboenaiqwjwpbbaraeyt.supabase.co/functions/v1/supplier-api/v1/orders?status=placed" \
  -H "Authorization: Bearer $GARAGY_KEY"

Move an order as in the portal: confirm_fitment, accept, reject (with a reason the buyer sees), ready, dispatched, delivered. A new order not accepted within 30 minutes is cancelled and refunded.

curl -X POST "https://nboenaiqwjwpbbaraeyt.supabase.co/functions/v1/supplier-api/v1/orders/ORD-2026-000123/reject" \
  -H "Authorization: Bearer $GARAGY_KEY" \
  -H "Content-Type: application/json" \
  -d '{"reason":"Out of stock at the branch"}'

خطافات الويب

The owner adds your address in Selling → Webhooks. Garagy posts JSON for the events chosen: order.placed, order.status, rfq.new, stock.changed (stock moved in Garagy: a sale, a job, a return, a count; changes your own system sent are not echoed back). A non-2xx answer is tried again after 1, 2, 4, 8 and 16 minutes.

Headers: x-garagy-event, x-garagy-delivery (same on a retry), x-garagy-signature: sha256=<hex HMAC-SHA256 of the body with your webhook secret>. Check it before trusting the body:

import { createHmac, timingSafeEqual } from "node:crypto";
const expected = "sha256=" + createHmac("sha256", process.env.GARAGY_WEBHOOK_SECRET).update(rawBody).digest("hex");
const ok = timingSafeEqual(Buffer.from(expected), Buffer.from(req.headers["x-garagy-signature"] ?? ""));

الإجابات

200 done (an upload lists rejected rows in errors), 400 bad request, 401 invalid or revoked key, 404 not found or not yours, 413 too large, 422 refused (the message says why, e.g. the shop is read-only or the order cannot move from its status), 429 too many calls.

جراجي