API Endpoint Catalog¶
Base: https://api.yam3at.com/api/v1 — envelope, errors, pagination, and headers per conventions. Auth column: Public, Customer, Vendor (approved vendor team member), Admin, Any (any authenticated user). All endpoints MVP unless the Phase column says otherwise.
Auth & Identity¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| POST | /auth/register |
Public | Customer registration (email or phone) | MVP |
| POST | /auth/login |
Public | Email/phone + password login → token | MVP |
| POST | /auth/otp/request |
Public | Send OTP (login / verify / reset) | MVP |
| POST | /auth/otp/verify |
Public | Verify OTP → token or verification flag | MVP |
| POST | /auth/social |
Public | Google/Apple ID-token sign-in | MVP |
| POST | /auth/password/forgot / /auth/password/reset |
Public | Reset flow | MVP |
| POST | /auth/logout |
Any | Revoke current token | MVP |
| GET / PATCH | /me |
Any | Read / update own profile, locale | MVP |
| GET / DELETE | /me/sessions |
Any | List / revoke device tokens | MVP |
| DELETE | /me |
Any | Account deletion request (DPPR) | MVP |
Vendors & Onboarding¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| POST | /vendors |
Any | Register vendor business (→ pending_review) |
MVP |
| GET / PATCH | /vendors/me |
Vendor | Own vendor profile | MVP |
| POST | /vendors/me/documents |
Vendor | Attach license document (media id) | MVP |
| GET | /vendors/me/documents |
Vendor | Document statuses | MVP |
| GET | /vendors/me/team · POST · DELETE /vendors/me/team/{id} |
Vendor owner | Team members (plan-limited) | MVP |
| GET | /vendors/me/analytics |
Vendor | Views, RFQs, quote win rate (plan-gated depth) | MVP |
| GET | /vendors/me/calendar |
Vendor | Availability calendar | Scale |
Subscriptions & Billing¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET | /plans |
Public | Active plans for country | MVP |
| POST | /subscriptions |
Vendor owner | Subscribe / upgrade (idempotent; may return payment_url) | MVP |
| GET | /subscriptions/me |
Vendor | Current subscription + quota usage | MVP |
| PATCH | /subscriptions/me |
Vendor owner | Toggle auto-renew, cancel at period end | MVP |
| GET | /invoices · GET /invoices/{id} |
Vendor | Billing history (PDF link) | MVP |
Marketplace & Search¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET | /categories |
Public | Category tree (bilingual) | MVP |
| GET | /search/vendors |
Public | Faceted vendor search (Meilisearch) | MVP |
| GET | /search/services |
Public | Service/package search | MVP |
| GET | /vendors/{id} |
Public | Public vendor profile + gallery + reviews summary | MVP |
| GET | /vendors/{id}/services |
Public | Published services & packages | MVP |
| GET | /cities / /countries |
Public | Reference data | MVP |
Listings (Vendor-side)¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET / POST | /vendors/me/services |
Vendor | List / create services | MVP |
| GET / PATCH / DELETE | /vendors/me/services/{id} |
Vendor | Manage service (publish/archive) | MVP |
| POST / PATCH / DELETE | /vendors/me/services/{id}/packages… |
Vendor | Manage packages | MVP |
| POST | /media |
Any | Pre-signed upload (declares context, type, size) | MVP |
| POST | /media/{id}/confirm |
Any | Confirm upload → async verification | MVP |
Events¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET / POST | /events |
Customer | List / create own events | MVP |
| GET / PATCH / DELETE | /events/{id} |
Customer | Manage event | MVP |
| GET | /events/{id}/summary |
Customer | RFQs, bookings, payments rollup | MVP |
| — | /events/{id}/budget · /checklist · /guests · /timeline |
Customer | Planner suite | Scale |
RFQs & Quotations¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| POST | /rfqs |
Customer | Create RFQ (draft or publish) under an event | MVP |
| GET | /rfqs · GET /rfqs/{id} |
Customer | Own RFQs with per-vendor statuses | MVP |
| POST | /rfqs/{id}/publish / /rfqs/{id}/cancel |
Customer | State transitions | MVP |
| GET | /vendor/rfqs · GET /vendor/rfqs/{id} |
Vendor | RFQ inbox (marks viewed) |
MVP |
| POST | /vendor/rfqs/{id}/decline |
Vendor | Decline with reason | MVP |
| POST | /quotations |
Vendor | Submit quotation (quota-gated) | MVP |
| PATCH | /quotations/{id} |
Vendor | Revise during negotiation / withdraw | MVP |
| GET | /rfqs/{id}/quotations |
Customer | Compare quotations | MVP |
| POST | /quotations/{id}/accept / /reject |
Customer | Accept (→ booking) / reject | MVP |
Bookings & Payments¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET | /bookings · GET /bookings/{id} |
Customer/Vendor | Own bookings (role-scoped view) | MVP |
| POST | /bookings/{id}/cancel |
Customer | Cancel per policy | MVP |
| POST | /bookings/{id}/refund-request |
Customer | Request refund (→ refund_requested) |
MVP |
| POST | /vendor/bookings/{id}/complete |
Vendor | Mark completed after service date | MVP |
| POST | /payments |
Customer/Vendor | Create payment session (booking deposit / invoice) | MVP |
| GET | /payments/{id} |
Payer | Poll payment status | MVP |
| POST | /webhooks/psp |
PSP (signed) | Payment/refund webhook | MVP |
| GET | /wallet |
Any | Wallet balance & ledger | Scale |
Conversations & Messages¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET | /conversations |
Customer/Vendor | Inbox, sorted by last_message_at |
MVP |
| POST | /conversations |
Customer | Open conversation with vendor (context: rfq/booking) | MVP |
| GET | /conversations/{id}/messages |
Participant | Cursor-paginated history | MVP |
| POST | /conversations/{id}/messages |
Participant | Send text / image / pdf | MVP |
| POST | /conversations/{id}/read |
Participant | Mark read | MVP |
Notifications¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| GET | /notifications |
Any | In-app inbox (cursor) | MVP |
| POST | /notifications/read |
Any | Mark (all/ids) read | MVP |
| POST / DELETE | /notifications/devices |
Any | Register / remove FCM token | MVP |
| GET / PATCH | /notifications/preferences |
Any | Channel preferences | MVP |
Reviews & Favorites¶
| Method | Path | Auth | Purpose | Phase |
|---|---|---|---|---|
| POST | /reviews |
Customer | Review a completed booking (one per booking) | MVP |
| GET | /vendors/{id}/reviews |
Public | Published reviews, paginated | MVP |
| POST | /reviews/{id}/reply |
Vendor | Single vendor reply | MVP |
| POST / DELETE | /favorites/{vendorId} |
Customer | Save / unsave vendor | MVP |
| GET | /favorites |
Customer | Saved vendors | MVP |
Admin (prefix /admin, role admin + granular permissions)¶
| Method | Path | Purpose | Phase |
|---|---|---|---|
| GET | /admin/vendors?status=pending_review |
Approval queue | MVP |
| POST | /admin/vendors/{id}/approve / /reject / /suspend |
Vendor lifecycle | MVP |
| GET / PATCH | /admin/users · /admin/users/{id} |
Customer management | MVP |
| CRUD | /admin/plans · /admin/categories · /admin/cms-pages |
Platform config & CMS | MVP |
| GET | /admin/rfqs · /admin/bookings · /admin/payments |
Oversight views | MVP |
| POST | /admin/refunds |
Execute refund (idempotent) | MVP |
| GET | /admin/reviews?status=flagged · POST /admin/reviews/{id}/hide |
Moderation | MVP |
| GET | /admin/audit-logs |
Audit trail (read-only) | MVP |
| GET | /admin/reports/revenue · /reports/activity |
Financial & activity reporting | MVP |
Reference Examples¶
The eight flows that define the product. Headers shown only where they matter; envelope per conventions.
1. Register (customer)¶
POST /auth/register
{
"name": "Noura Al-Sabah",
"email": "noura@example.com",
"phone": "+96555123456",
"password": "correct-horse-battery",
"locale": "ar"
}
201 Created
{
"data": {
"user": {
"id": "01J9ZKA2P4X6Y8Z0B2C4D6E8F0",
"name": "Noura Al-Sabah",
"email": "noura@example.com",
"email_verified": false,
"phone": "+96555123456",
"phone_verified": false,
"user_type": "customer",
"locale": "ar"
},
"token": "1|kR9v...sanctum...",
"verification": { "email_sent": true, "otp_sent_to": "+96555123456" }
},
"meta": {}
}
Errors: 422 VALIDATION_FAILED (duplicate email/phone reported per-field), 429 RATE_LIMITED.
2. Create Event¶
POST /events — Customer, phone or email verified.
{
"title": "زواج فهد ونورة",
"event_type": "wedding",
"event_date": "2026-11-20",
"event_time": "19:00",
"guests_expected": 350,
"budget_total": "12000.000",
"city_id": "01J9ZKC1TX...",
"location_text": "قاعة في منطقة الجهراء",
"notes": "نفضل قاعة منفصلة للرجال والنساء"
}
201 Created
{
"data": {
"id": "01J9ZKD3VQ...",
"title": "زواج فهد ونورة",
"event_type": "wedding",
"event_date": "2026-11-20",
"event_time": "19:00",
"guests_expected": 350,
"budget": { "amount": "12000.000", "currency": "KWD" },
"city": { "id": "01J9ZKC1TX...", "name": "الجهراء", "name_en": "Al Jahra" },
"status": "planning",
"created_at": "2026-07-05T10:12:00Z"
},
"meta": {}
}
3. Create & Publish RFQ¶
POST /rfqs — Customer owns the event; ≤ 10 target vendors.
{
"event_id": "01J9ZKD3VQ...",
"category_id": "01J9ZKCAT9...",
"description": "نحتاج بوفيه عشاء لـ 350 شخص، أطباق كويتية وخليجية، مع خدمة تقديم كاملة وطاقم نسائي لقسم النساء.",
"budget_min": "2500.000",
"budget_max": "4000.000",
"vendor_ids": ["01J9ZKVN01...", "01J9ZKVN02...", "01J9ZKVN03..."],
"attachment_media_ids": ["01J9ZKMED1..."],
"publish": true
}
201 Created
{
"data": {
"id": "01J9ZKRFQ1...",
"event_id": "01J9ZKD3VQ...",
"category": { "id": "01J9ZKCAT9...", "name": "الضيافة والتموين", "name_en": "Catering & Hospitality" },
"status": "pending",
"budget_min": { "amount": "2500.000", "currency": "KWD" },
"budget_max": { "amount": "4000.000", "currency": "KWD" },
"expires_at": "2026-07-12T10:15:00Z",
"vendors": [
{ "vendor_id": "01J9ZKVN01...", "status": "sent" },
{ "vendor_id": "01J9ZKVN02...", "status": "sent" },
{ "vendor_id": "01J9ZKVN03...", "status": "sent" }
]
},
"meta": {}
}
Errors: 403 AUTH_EMAIL_UNVERIFIED, 422 VALIDATION_FAILED (budget_max < budget_min, > 10 vendors, vendor not approved/in category), 429 (10 RFQs/day).
4. Submit Quotation (vendor)¶
POST /quotations — Vendor targeted by the RFQ; decrements monthly quota.
{
"rfq_id": "01J9ZKRFQ1...",
"items": [
{ "description": "بوفيه عشاء ملكي - 350 شخص", "quantity": 350, "unit_price": "8.500" },
{ "description": "طاقم خدمة نسائي (6 موظفات)", "quantity": 6, "unit_price": "45.000" },
{ "description": "ركن قهوة عربية وشاي", "quantity": 1, "unit_price": "150.000" }
],
"notes": "السعر شامل التوصيل والتجهيز قبل الحفل بـ 3 ساعات.",
"valid_until": "2026-07-19",
"delivery_time_days": 2,
"attachment_media_ids": ["01J9ZKMED2..."]
}
201 Created
{
"data": {
"id": "01J9ZKQUO1...",
"rfq_id": "01J9ZKRFQ1...",
"revision": 1,
"items": [
{ "description": "بوفيه عشاء ملكي - 350 شخص", "quantity": 350, "unit_price": "8.500", "line_total": "2975.000" },
{ "description": "طاقم خدمة نسائي (6 موظفات)", "quantity": 6, "unit_price": "45.000", "line_total": "270.000" },
{ "description": "ركن قهوة عربية وشاي", "quantity": 1, "unit_price": "150.000", "line_total": "150.000" }
],
"total": { "amount": "3395.000", "currency": "KWD" },
"valid_until": "2026-07-19",
"status": "submitted",
"quota": { "used_this_month": 13, "limit": 30 }
},
"meta": {}
}
Errors: 403 SUBSCRIPTION_QUOTA_EXCEEDED, 403 VENDOR_NOT_APPROVED, 409 RFQ_INVALID_STATE (expired/cancelled RFQ).
5. Accept Quotation → Booking¶
POST /quotations/01J9ZKQUO1.../accept — Customer owning the RFQ. Atomic transaction: quotation accepted, RFQ accepted, sibling quotations rejected, booking created pending.
{ "deposit_option": "deposit" }
201 Created
{
"data": {
"booking": {
"id": "01J9ZKBKG1...",
"event_id": "01J9ZKD3VQ...",
"vendor": { "id": "01J9ZKVN02...", "name": "ضيافة الديوان", "name_en": "Al Diwan Catering" },
"quotation_id": "01J9ZKQUO1...",
"total": { "amount": "3395.000", "currency": "KWD" },
"deposit_due": { "amount": "679.000", "currency": "KWD" },
"amount_paid": { "amount": "0.000", "currency": "KWD" },
"service_date": "2026-11-20",
"status": "pending",
"payment_deadline": "2026-07-08T10:30:00Z"
},
"next_action": { "type": "payment_required", "endpoint": "/api/v1/payments" }
},
"meta": {}
}
Errors: 409 QUOTATION_EXPIRED, 409 QUOTATION_INVALID_STATE, 403 AUTH_PHONE_UNVERIFIED (verification required before money moves).
6. Create Payment (deposit via KNET)¶
POST /payments — Customer; header Idempotency-Key: 3f7c2e9a-... required.
{
"payable_type": "booking",
"payable_id": "01J9ZKBKG1...",
"kind": "deposit",
"return_url": "https://yam3at.com/ar/bookings/01J9ZKBKG1/payment-result"
}
201 Created
{
"data": {
"id": "01J9ZKPAY1...",
"payable_type": "booking",
"payable_id": "01J9ZKBKG1...",
"amount": { "amount": "679.000", "currency": "KWD" },
"status": "pending",
"provider": "myfatoorah",
"payment_url": "https://portal.myfatoorah.com/kwt/ie/01072026-abc123",
"expires_at": "2026-07-05T11:00:00Z"
},
"meta": {}
}
Client opens payment_url (webview/redirect), user pays with KNET, then client polls GET /payments/01J9ZKPAY1... until succeeded — the transition itself comes from the webhook (next example). Errors: 503 PAYMENT_PROVIDER_UNAVAILABLE, 409 IDEMPOTENCY_KEY_REUSED, 409 BOOKING_INVALID_STATE.
7. PSP Webhook (inbound)¶
POST /webhooks/psp — signed by provider; no bearer auth. Provider-specific payload normalized by the adapter; illustrative shape:
{
"event": "payment.captured",
"reference": "01J9ZKPAY1...",
"provider_ref": "MF-INV-88231245",
"amount": "679.000",
"currency": "KWD",
"method": "knet",
"captured_at": "2026-07-05T10:41:22Z"
}
Server: verify HMAC signature → match reference to payment → verify amount 679.000 and currency KWD exactly → transition pending → succeeded (idempotent) → emit PaymentSucceeded → queued listeners confirm booking (pending → confirmed) and notify both parties.
200 OK
{ "data": { "received": true }, "meta": {} }
Signature failure → 401 (dropped, alarmed). Amount mismatch → 200 (acknowledged to stop retries) but payment marked flagged + ops alert — never confirmed. See Integrations.
8. Search Vendors¶
GET /search/vendors?q=قاعات&category_id=01J9ZKCAT2...&city_id=01J9ZKC1TX...&price_min=1000&price_max=5000&rating_min=4&sort=-rating&page=1&per_page=20 — Public. Accept-Language: ar.
200 OK
{
"data": [
{
"id": "01J9ZKVN07...",
"name": "قاعة الياسمين",
"name_ar": "قاعة الياسمين",
"name_en": "Al Yasmin Hall",
"slug": "al-yasmin-hall",
"categories": [ { "id": "01J9ZKCAT2...", "name": "قاعات الأفراح" } ],
"city": { "id": "01J9ZKC1TX...", "name": "الجهراء" },
"rating": 4.8,
"reviews_count": 127,
"price_from": { "amount": "1500.000", "currency": "KWD" },
"is_featured": true,
"cover_image": "https://cdn.yam3at.com/vendors/01J9ZKVN07/cover_800.webp",
"distance_km": null
}
],
"meta": {
"pagination": { "page": 1, "per_page": 20, "total": 34, "total_pages": 2 },
"facets": {
"city_id": { "01J9ZKC1TX...": 34 },
"rating_min": { "4": 34, "4.5": 21 }
},
"query_time_ms": 9
},
"links": { "next": "/api/v1/search/vendors?...&page=2", "prev": null }
}
Degraded mode (Meilisearch down): 503 SEARCH_UNAVAILABLE; clients fall back to GET /categories browse.
Related: Conventions · ERD · Tables · Integrations