كل طلب خارج العينة يحتاج Authorization: Bearer dp_live_…. المفتاح المفقود أو غير الصحيح أو المجهول أو الملغى أو المنتهي يعيد 401 unauthorized (نفس الإجابة دائمًا: لا نكشف السبب). المفتاح الصحيح الذي لا تسمح خطته أو صلاحياته أو قائمة IP بنقطة النهاية يعيد 403 forbidden مع details.required_scope أو details.plan.
المفاتيح: dp_live_ + 40 حرفًا base32 من 25 بايت عشوائي؛ نخزن تجزئة SHA-256 فقط. الصلاحيات: drugs:read وchanges:read وexport وwebhooks. التدوير يبقي المفتاح القديم 24 ساعة؛ الإلغاء فوري.
الترقيم
القوائم تأخذ limit (1–100، الافتراضي 20) وcursor وتعيد page: { limit, has_more, next_cursor }. المؤشر نص موقّع غير مقروء، صالح 24 ساعة ومرتبط بالترتيب والمرشحات (تغيير مرشح يعيد 400 invalid_cursor). القوائم تستخدم مؤشرات keyset تبقى ثابتة مع تغير البيانات؛ نتائج البحث (q) مرتبة بالصلة ومحدودة بـ 1,000. لا تحمل القوائم عددًا إجماليًا؛ /meta فيه أعداد المجموعة.
شكل واحد لكل إجابة غير 2xx: { "error": { "code", "message", "details" } }. message للمطورين؛ details بنية منظمة (كائن، أو مصفوفة { param, issue } لأخطاء التحقق، أو null).
الأخطاء
الحقل
النوع
الوصف
مثال
400 validation_error
النوع: details[]
كل معامل غير صحيح مع param وissue.
400 invalid_cursor
النوع: —
مؤشر منتهٍ أو تالف أو من مرشحات أخرى.
400 since_too_old
النوع: window_days
since خارج نافذة خطتك: أعد التحميل من /drugs.
401 unauthorized
النوع: —
مفتاح مفقود أو تالف أو مجهول أو ملغى أو منتهٍ.
403 forbidden
النوع: plan, required_scope, reason
الخطة أو الصلاحية أو حساب موقوف أو اشتراك منتهٍ.
403 ip_not_allowed
النوع: —
قائمة IP لخطة Enterprise.
404 not_found
النوع: —
معرّف أو مسار مجهول.
301 moved
النوع: new_id + Location
المعرّف قديم؛ اتبع Location.
429 rate_limited
النوع: retry_after
حد الدقيقة؛ ترويسة Retry-After.
429 quota_exceeded
النوع: resets_at
الحصة الشهرية؛ Retry-After حتى بداية الشهر.
500 internal_error
النوع: request_id
خطأ من جهتنا؛ اذكر request_id للدعم.
503 unavailable
النوع: —
صيانة أو قاعدة بيانات غير متاحة؛ Retry-After.
الحدود
لكل مفتاح: حد في الدقيقة وحصة شهرية (الشهر التقويمي بتوقيت UTC)، كلاهما من خطتك. العينة محدودة لكل شبكة مصدر (30 في الدقيقة، 300 في اليوم). كل استجابة تحمل X-RateLimit-Limit وX-RateLimit-Remaining وX-RateLimit-Reset (ثوانٍ Unix)، وللمفاتيح X-Quota-Limit وX-Quota-Remaining وX-Quota-Reset. عند التجاوز: 429 مع Retry-After. استجابات 304 و4xx تُحسب طلبات؛ 5xx لا تُحسب. أرسل If-None-Match بقيمة ETag التي استلمتها لتحصل على 304 مجانية عندما لا يتغير شيء.
دليل المزامنة الجزئية
التغذية GET /price-changes?since= تعيد أحداثًا تُضاف فقط ومرتبة بـ id: price_changed وadded وstatus_changed وremoved وrenamed. كل حدث يحمل السجل الحالي (drug)، فطلب واحد يكفي لتحديث نسختك.
أول مزامنة: حمّل الكتالوج من GET /drugs (كل الصفحات) واحفظ meta.generated_at.
كل N دقيقة: GET /price-changes?since=<المحفوظ>؛ تابع الصفحات بـ cursor (يحمل since الأصلي)؛ طبّق كل حدث؛ احفظ latest_detected_at.
since شامل والتسليم at-least-once: تجاوز معرّفات الأحداث التي طبّقتها.
since أقدم من نافذة خطتك يعيد 400 since_too_old: أعد التحميل كاملًا.
حلقة المزامنة (JavaScript)
let since = stored.latest_detected_at; // from the previous run
let cursor = null;
do {
const url = cursor ? `https://api.dwaprice.com/v1/price-changes?cursor=${encodeURIComponent(cursor)}`
: `https://api.dwaprice.com/v1/price-changes?since=${since}&limit=100`;
const page = await (await fetch(url, { headers: { Authorization: "Bearer " + KEY } })).json();
for (const e of page.data) {
if (e.id <= stored.last_event_id) continue; // at-least-once: skip what you applied
applyEvent(e); // e.type, e.data, e.drug (current record)
stored.last_event_id = e.id;
}
if (page.latest_detected_at) stored.latest_detected_at = page.latest_detected_at;
cursor = page.page.next_cursor;
} while (cursor);
Drugs
Products, lookups, alternatives and price history.
GET/drugs
List or search drugs
Without q: the catalogue, filtered and sorted (keyset cursor, stable across updates). With q: typo-tolerant search over Arabic and English trade names, approved aliases and spelling variants, active ingredients and barcodes; ranked, at most 1,000 results.
المعاملات
GET /drugs parameters
Field
Type
Description
Example
q (query)
Type: string
Search text, 2–80 characters (Arabic or English; typo-tolerant).
كونجستل
company (query)
Type: string
Company id (see `/companies`).
sigma
ingredient (query)
Type: string
Ingredient id (see `/ingredients`); products containing it.
paracetamol
atc (query)
Type: string
ATC code prefix, matched against product-level and ingredient-level codes (`J01` matches `J01CR02`).
N02BE
dosage_form (query)
Type: DosageFormClass
route (query)
Type: RouteClass
prescription_status (query)
Type: PrescriptionStatus
status (query)
Type: ListingStatus
Default is all statuses.
has_barcode (query)
Type: boolean
updated_since (query)
Type: string (date-time)
Records whose `updated_at` is after this timestamp (any field change). For price changes alone use `/price-changes`.
sort (query)
Type: name | price | -price | updated_at | -updated_at
Ignored when `q` is given (results are ranked by relevance).
default "name"
limit (query)
Type: integer
default 20
cursor (query)
Type: string
Opaque cursor from `page.next_cursor` of the previous response.
الاستجابات
200 A page of drugs. → DrugList
400 Invalid parameter, cursor or `since`. → Error
401 Missing, malformed, unknown, revoked or expired key. → Error
403 Key valid, but the plan, scope or IP does not allow this request. → Error
429 Per-minute limit or monthly quota exceeded; `Retry-After` in seconds. → Error
500 Our fault; quote `request_id` to support. → Error
Returns a list: in the source price lists 73 barcodes are shared by more than one pack (e.g. two pack sizes of one product). Ordered listed first, then newest price date. An unknown barcode gives an empty list.
Products with the same active ingredients and the same strength, cheapest first (no price last). strength=any appends products with the same ingredients at another strength.
المعاملات
GET /drugs/{id}/alternatives parameters
Field
Type
Description
Example
id (path)*
Type: string
Stable public id (the product's URL slug).
congestal-20-tabs
strength (query)
Type: same | any
default "same"
limit (query)
Type: integer
default 50
cursor (query)
Type: string
Opaque cursor from `page.next_cursor` of the previous response.
الاستجابات
200 Alternatives. → AlternativeList
401 Missing, malformed, unknown, revoked or expired key. → Error
403 Key valid, but the plan, scope or IP does not allow this request. → Error
404 Unknown id or path. → Error
429 Per-minute limit or monthly quota exceeded; `Retry-After` in seconds. → Error
500 Our fault; quote `request_id` to support. → Error
Append-only events ordered by id: price_changed, added, status_changed, removed, renamed. Each event carries the current record, so one call updates a local copy. Sync loop: store latest_detected_at, call again with it as since, page with cursor, skip event ids already applied (delivery is at-least-once). since older than the plan's feed window → 400 since_too_old (reload with /drugs). Requires scope changes:read.
المعاملات
GET /price-changes parameters
Field
Type
Description
Example
since (query)
Type: string (date-time)
Events with `detected_at` at or after this timestamp (inclusive; skip event ids already applied). Required unless `cursor` is given — a cursor carries the original `since`.
2026-10-21T00:00:00Z
type (query)
Type: string
Comma-separated event types; default all.
price_changed,status_changed
limit (query)
Type: integer
default 20
cursor (query)
Type: string
Opaque cursor from `page.next_cursor` of the previous response.
الاستجابات
200 A page of events. → PriceChangeList
400 Invalid parameter, cursor or `since`. → Error
401 Missing, malformed, unknown, revoked or expired key. → Error
403 Key valid, but the plan, scope or IP does not allow this request. → Error
429 Per-minute limit or monthly quota exceeded; `Retry-After` in seconds. → Error
500 Our fault; quote `request_id` to support. → Error
Batches of events are POSTed within 10 minutes of each dataset capture, signed with X-Dwaprice-Signature: sha256=<HMAC-SHA256 of the raw body with the secret> and X-Dwaprice-Delivery: <id>. Non-2xx answers are retried with exponential back-off for 24 hours; then the webhook is paused and the admin alerted. Requires scope webhooks.
الاستجابات
201 Created; `secret` is shown only in this response. → object
400 Invalid parameter, cursor or `since`. → Error
401 Missing, malformed, unknown, revoked or expired key. → Error
403 Key valid, but the plan, scope or IP does not allow this request. → Error
الإصدار الأول: الأدوية، البحث، الباركود، البدائل، تاريخ السعر، تغذية التغييرات، الشركات، المواد الفعالة، meta؛ عينة بلا مفتاح؛ التصدير والـ webhooks لخطة Enterprise.
التغييرات الإضافية (حقول ومعاملات ونقاط نهاية وقيم جديدة) تصدر في /v1 وتُسجَّل هنا؛ على العملاء تجاهل الحقول والقيم المجهولة. التغييرات غير المتوافقة تصدر في /v2 مع إبقاء /v1 اثني عشر شهرًا والإعلان بترويستي Deprecation وSunset.