المطورين

متاح الآن

واجهة غاية البرمجية (API)

احصل على الأسعار، وأنشئ الشحنات، واطبع البوالص، واستقبل تحديثات التتبع — مباشرة من متجرك أو نظامك.

البداية

1

أنشئ مفتاح اختبار

من بوابة التاجر ← المطورين والـ API. مفاتيح الاختبار تعمل فوراً.

2

ابنِ واختبر

شحنات الاختبار تجريبية — بوليصة تجريبية وحالات تتحرك لحالها، بدون خصم من المحفظة وبدون مندوب.

3

انتقل للتشغيل الفعلي

وثّق نشاطك، وأنشئ مفتاحاً حقيقياً، واستبدل المفتاح فقط — نفس الرابط ونفس الكود.

الرابط الأساسي

https://os.ghayaex.com/v1/api

نفس الرابط للاختبار والتشغيل — المفتاح هو اللي يحدد.

المرجع الكامل للـ API

https://os.ghayaex.com/v1/api/docs

ملف OpenAPI

المصادقة

أرسل مفتاحك في ترويسة Authorization مع كل طلب. كل مفتاح له فقط الصلاحيات التي اخترتها عند إنشائه (مثلاً: الشحنات قراءة وكتابة، المدن قراءة).

HTTP
Authorization: Bearer gx_test_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Idempotency-Key: order-10045   # POST only — safe retries
Content-Type: application/json
  • احفظ المفاتيح على السيرفر فقط — أبداً في موقع أو تطبيق أو مستودع عام.
  • استخدم مفتاحاً منفصلاً لكل نظام حتى تلغي أحدها دون التأثير على البقية.
  • يمكنك ربط المفتاح بعناوين IP سيرفرك وتحديد تاريخ انتهاء.
  • جدّد المفتاح في أي وقت من البوابة، ويتوقف القديم فوراً.

الواجهات

GET/ping—

تأكد إن المفتاح شغّال وشوف وضعه (اختبار أو حقيقي).

الرد
{ "ok": true, "mode": "test", "merchant": { "id": "…", "name": "My Store" } }
POST/ratesshipments:read

أسعارك لكل شركات الشحن (الأرخص أولاً) قبل الحجز. ما في حجز ولا خصم.

الطلب
{
  "parcel": { "weightKg": 2 },
  "cod": { "amount": 249 },
  "receiverCity": "Jeddah"
}
الرد
{
  "object": "list",
  "data": [
    { "carrier": "smsa", "name": { "ar": "سمسا", "en": "SMSA" }, "price": { "net": 22, "vat": 3.3, "total": 25.3, "currency": "SAR" } },
    { "carrier": "aramex", "name": { "ar": "أرامكس", "en": "Aramex" }, "price": { "net": 24, "vat": 3.6, "total": 27.6, "currency": "SAR" } }
  ]
}
POST/shipmentsshipments:write

احجز شحنة واحصل على رقم البوليصة والسعر ورابط البوليصة. المرسل هو عنوان الاستلام بحسابك. أرسل Idempotency-Key حتى لا تُحجز الشحنة مرتين عند إعادة المحاولة.

الطلب
{
  "carrier": "aramex",
  "reference": "order-10045",
  "receiver": { "name": "Noura", "phone": "0551234567", "city": "Jeddah", "line1": "Al Andalus, Tahlia St 12" },
  "parcel": { "weightKg": 2, "pieces": 1, "description": "Perfume" },
  "cod": { "amount": 249 }
}
الرد
{
  "id": "6f0c2a1e-…",
  "object": "shipment",
  "mode": "live",
  "awb": "44012345678",
  "carrier": "aramex",
  "status": "created",
  "reference": "order-10045",
  "cod": { "amount": 249, "currency": "SAR" },
  "price": { "net": 24, "vat": 3.6, "total": 27.6, "currency": "SAR" },
  "labelUrl": "https://os.ghayaex.com/v1/api/shipments/6f0c2a1e-…/label",
  "createdAt": "2026-10-27T09:41:12.000Z",
  "events": [ { "status": "created", "description": "Booked with carrier", "at": "2026-10-27T09:41:14.000Z" } ]
}
GET/shipments/{id | awb}shipments:read

الحالة الحالية وسجل التتبع كاملاً، برقمنا أو برقم البوليصة.

الرد
{
  "awb": "44012345678",
  "status": "out_for_delivery",
  "events": [
    { "status": "out_for_delivery", "location": "Jeddah", "at": "2026-10-28T08:30:00.000Z" },
    { "status": "in_transit", "location": "Jeddah hub", "at": "2026-10-28T06:15:00.000Z" },
    { "status": "picked_up", "location": "Riyadh", "at": "2026-10-27T13:02:00.000Z" }
  ],
  …
}
GET/shipments?status=delivered&page=1&pageSize=25shipments:read

شحناتك، الأحدث أولاً، مع فلترة بالحالة والمرجع والتاريخ.

الرد
{ "object": "list", "data": [ … ], "page": 1, "pageSize": 25, "total": 1, "hasMore": false }
GET/shipments/{id}/labelshipments:read

تحميل البوليصة بصيغة PDF جاهزة للطباعة.

الرد
%PDF-1.7 … (application/pdf)
POST/shipments/{id}/cancelshipments:write

الإلغاء قبل الاستلام، والمبلغ يرجع لمحفظتك.

الرد
{ "id": "6f0c2a1e-…", "status": "canceled", … }
GET/carriersshipping-companies:read

شركات الشحن المتاحة لحسابك.

الرد
{ "object": "list", "data": [ { "code": "aramex", "name": { "ar": "أرامكس", "en": "Aramex" }, "cod": true, "cancelable": false } ] }
GET/cities?q=jedcities:read

المدن بالعربي والإنجليزي، مع فلترة حسب شركة الشحن.

الرد
{ "object": "list", "data": [ { "name": { "en": "Jeddah", "ar": "جدة" } } ], "total": 1 }
GET/accountwallet:read

رصيد المحفظة ورصيد التحصيل.

الرد
{ "object": "account", "wallet": { "balance": 512.4, "currency": "SAR" }, "cod": { "balance": 1890, "currency": "SAR" } }

إشعارات الويب هوك

أضف رابط HTTPS في البوابة واختر الأحداث التي تريدها. نرسل طلب POST بمحتوى JSON موقّع بالرمز السري الخاص برابطك.

shipment.createdshipment.status_changedshipment.deliveredshipment.returnedshipment.canceledcod.settledwallet.low_balance
مثال على إشعار
POST https://your-store.com/webhooks/ghaya
X-GHAYA-Event: shipment.delivered
X-GHAYA-Delivery: evt_3f9c…
X-GHAYA-Signature: t=1761559200,v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd

{
  "id": "evt_3f9c…",
  "object": "event",
  "type": "shipment.delivered",
  "mode": "live",
  "created": "2026-10-28T10:04:00.000Z",
  "data": { "id": "6f0c2a1e-…", "awb": "44012345678", "reference": "order-10045", "status": "delivered", "previousStatus": "out_for_delivery", … }
}
التحقق من التوقيع
import crypto from 'node:crypto'

// rawBody = the exact request body as received (before JSON.parse)
export function verifyGhaya(rawBody, signatureHeader, secret) {
  const p = Object.fromEntries(signatureHeader.split(',').map((x) => x.split('=')))
  if (Math.abs(Date.now() / 1000 - Number(p.t)) > 300) return false // older than 5 min
  const expected = crypto.createHmac('sha256', secret).update(`${p.t}.${rawBody}`).digest('hex')
  return expected.length === p.v1.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(p.v1))
}
  • تحقق دائماً من X-GHAYA-Signature وارفض أي إشعار أقدم من 5 دقائق.
  • رد بأي رمز 2xx خلال 10 ثوانٍ، ونفّذ العمل الثقيل بعدها.
  • نعيد محاولة الإرسال الفاشل 6 مرات خلال حوالي 21 ساعة بنفس معرّف الحدث (X-GHAYA-Delivery) — استخدمه لمنع التكرار.
  • رابط الاختبار يستقبل أحداث مفاتيح الاختبار فقط، والحقيقي يستقبل الأحداث الحقيقية فقط.

الأخطاء

الأخطاء برموز HTTP القياسية مع محتوى JSON: { "error": { "code": "invalid", "message": "…", "fields": ["receiver.phone"] }, "requestId": "req_…" }. كل رد فيه X-Request-Id، اذكره للدعم.

400invalid · invalid_weight · bad_json
401unauthorized · key_revoked · key_expired
402insufficient_balance · outstanding_balance
403forbidden_scope · ip_not_allowed
404not_found · shipment_not_found
409no_rate · not_cancelable · cancel_not_supported
422carrier_rejected
429rate_limited
500internal

الحدود وأفضل الممارسات

  • الاختبار: 60 طلباً في الدقيقة · الحقيقي: 600 في الدقيقة لكل مفتاح (رد 429 يتضمن Retry-After، وكل رد فيه X-RateLimit-Remaining).
  • حد اختياري بالساعة لكل مورد يُضبط على المفتاح.
  • القوائم مقسّمة بصفحات page و pageSize (حتى 100).
  • كل الأوقات بتوقيت UTC (ISO 8601) والمبالغ بالريال السعودي.

تحتاج مساعدة في الربط؟ تواصل معنا