Generated API reference
Endpoint reference generated at build time from the OpenAPI annotations in the Ebda Store API source. The raw document is available as /openapi.json (OpenAPI 3.0.0).
Stores
GET https://api.ebda.app/api/v1/stores
List all stores Get paginated list of all stores (admin only)
Requires authentication (Bearer access token or the auth cookie).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
page | query | integer | |
limit | query | integer |
Responses
200List of stores (object)401403
POST https://api.ebda.app/api/v1/stores
Create a new store Create a new store (admin only)
Requires authentication (Bearer access token or the auth cookie).
Request body
| Name | Type | Description |
|---|---|---|
name (required) | string | Example: "My Store" |
slug | string | Example: "my-store" |
domain | string | Example: "mystore.com" |
settings | object |
{
"name": "My Store",
"slug": "my-store",
"domain": "mystore.com",
"settings": null
}Responses
201Store created successfully (object)400401
Products
GET https://api.ebda.app/api/v1/stores/{storeId}/products
List products Get paginated list of products for a store
No authentication required.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
storeId (required) | path | string (uuid) | |
page | query | integer | |
limit | query | integer | |
status | query | string: "active" | "draft" | "archived" | |
category | query | string | |
search | query | string | |
featured | query | boolean | Omit for all products; 'true' or 'false' filters. Any other value is a 400. |
Responses
200List of products (object)
Authentication
POST https://api.ebda.app/api/v1/auth/register
Register a new user Create a new user account with email verification
No authentication required.
Request body
| Name | Type | Description |
|---|---|---|
email (required) | string (email) | Example: "user@example.com" |
password (required) | string | Example: "securePassword123" |
firstName | string | Example: "John" |
lastName | string | Example: "Doe" |
{
"email": "user@example.com",
"password": "securePassword123",
"firstName": "John",
"lastName": "Doe"
}Responses
200Verification email sent. Identical for new and existing emails (T1-4 enumeration close) — no user, tokens, cookies or csrfToken are issued; the session starts at /auth/login after verification. (object)400
POST https://api.ebda.app/api/v1/auth/login
Login user Authenticate user and return JWT tokens
No authentication required.
Request body
| Name | Type | Description |
|---|---|---|
email (required) | string (email) | |
password (required) | string |
{
"email": "string",
"password": "string"
}Responses
200Login successful (object)401Invalid credentials
Schemas
Error
| Name | Type | Description |
|---|---|---|
success | boolean | Example: false |
error | object | |
error.code | string | Example: "VALIDATION_ERROR" |
error.message | string | Example: "Invalid request data" |
Pagination
| Name | Type | Description |
|---|---|---|
page | integer | Example: 1 |
limit | integer | Example: 20 |
total | integer | Example: 100 |
totalPages | integer | Example: 5 |
User
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
email | string (email) | |
firstName | string | |
lastName | string | |
role | string: "customer" | "store_admin" | "super_admin" | |
isVerified | boolean | |
createdAt | string (date-time) |
Store
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
name | string | |
nameAr | string | |
slug | string | |
description | string | |
logo | string (uri) | |
domain | string | |
status | string: "active" | "suspended" | "pending" | |
createdAt | string (date-time) |
Product
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
storeId | string (uuid) | |
name | string | |
nameAr | string | |
slug | string | |
description | string | |
descriptionAr | string | |
price | integer | Price in piastres (1 EGP = 100 piastres) |
compareAtPrice | integer | |
sku | string | |
badgeLabel | string | |
badgeLabelAr | string | |
searchTerms | string | Extra words shoppers type (dialect / Franco / English); comma-separated, cleaned to "a, b, c". Searched, never displayed. null clears. |
inventory | integer | |
status | string: "active" | "draft" | "archived" | |
images | ProductImage[] | |
images.id | string (uuid) | |
images.url | string (uri) | |
images.alt | string | |
images.position | integer | |
category | Category | |
category.id | string (uuid) | |
category.name | string | |
category.nameAr | string | |
category.slug | string | |
category.description | string | |
category.descriptionAr | string | |
category.image | string (uri) | |
createdAt | string (date-time) |
ProductImage
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
url | string (uri) | |
alt | string | |
position | integer |
Category
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
name | string | |
nameAr | string | |
slug | string | |
description | string | |
descriptionAr | string | |
image | string (uri) |
Order
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
orderNumber | string | |
status | string: "pending" | "confirmed" | "processing" | "shipped" | "delivered" | "cancelled" | "refunded" | |
subtotal | integer | |
tax | integer | |
shipping | integer | |
total | integer | |
shippingAddress | object | |
billingAddress | object | |
items | OrderItem[] | |
items.id | string (uuid) | |
items.productId | string (uuid) | |
items.productName | string | |
items.sku | string | |
items.quantity | integer | |
items.price | integer | |
items.total | integer | |
customer | User | |
customer.id | string (uuid) | |
customer.email | string (email) | |
customer.firstName | string | |
customer.lastName | string | |
customer.role | string: "customer" | "store_admin" | "super_admin" | |
customer.isVerified | boolean | |
customer.createdAt | string (date-time) | |
createdAt | string (date-time) |
OrderItem
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
productId | string (uuid) | |
productName | string | |
sku | string | |
quantity | integer | |
price | integer | |
total | integer |
Cart
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
items | CartItem[] | |
items.id | string (uuid) | |
items.productId | string (uuid) | |
items.quantity | integer | |
items.product | Product | |
items.product.id | string (uuid) | |
items.product.storeId | string (uuid) | |
items.product.name | string | |
items.product.nameAr | string | |
items.product.slug | string | |
items.product.description | string | |
items.product.descriptionAr | string | |
items.product.price | integer | Price in piastres (1 EGP = 100 piastres) |
items.product.compareAtPrice | integer | |
items.product.sku | string | |
items.product.badgeLabel | string | |
items.product.badgeLabelAr | string | |
items.product.searchTerms | string | Extra words shoppers type (dialect / Franco / English); comma-separated, cleaned to "a, b, c". Searched, never displayed. null clears. |
items.product.inventory | integer | |
items.product.status | string: "active" | "draft" | "archived" | |
items.product.images | ProductImage[] | |
items.product.category | Category | |
items.product.createdAt | string (date-time) | |
itemCount | integer | |
subtotal | integer |
CartItem
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
productId | string (uuid) | |
quantity | integer | |
product | Product | |
product.id | string (uuid) | |
product.storeId | string (uuid) | |
product.name | string | |
product.nameAr | string | |
product.slug | string | |
product.description | string | |
product.descriptionAr | string | |
product.price | integer | Price in piastres (1 EGP = 100 piastres) |
product.compareAtPrice | integer | |
product.sku | string | |
product.badgeLabel | string | |
product.badgeLabelAr | string | |
product.searchTerms | string | Extra words shoppers type (dialect / Franco / English); comma-separated, cleaned to "a, b, c". Searched, never displayed. null clears. |
product.inventory | integer | |
product.status | string: "active" | "draft" | "archived" | |
product.images | ProductImage[] | |
product.images.id | string (uuid) | |
product.images.url | string (uri) | |
product.images.alt | string | |
product.images.position | integer | |
product.category | Category | |
product.category.id | string (uuid) | |
product.category.name | string | |
product.category.nameAr | string | |
product.category.slug | string | |
product.category.description | string | |
product.category.descriptionAr | string | |
product.category.image | string (uri) | |
product.createdAt | string (date-time) |
Review
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
rating | integer | |
title | string | |
comment | string | |
isVerified | boolean | |
isApproved | boolean | |
helpfulCount | integer | |
createdAt | string (date-time) |
Return
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
returnNumber | string | |
type | string: "return" | "exchange" | "refund" | |
status | string: "pending" | "approved" | "rejected" | "shipped" | "received" | "inspecting" | "completed" | "cancelled" | |
reason | string | |
refundAmount | integer | |
items | ReturnItem[] | |
items.id | string (uuid) | |
items.productId | string (uuid) | |
items.productName | string | |
items.quantity | integer | |
items.reason | string | |
items.condition | string | |
items.orderItem | object | |
items.orderItem.bundleGroupId | string (uuid) | |
items.orderItem.bundleName | string | |
items.orderItem.bundleNameAr | string | |
createdAt | string (date-time) |
ReturnItem
| Name | Type | Description |
|---|---|---|
id | string (uuid) | |
productId | string (uuid) | |
productName | string | |
quantity | integer | |
reason | string | |
condition | string | |
orderItem | object | |
orderItem.bundleGroupId | string (uuid) | |
orderItem.bundleName | string | |
orderItem.bundleNameAr | string |
DashboardStats
| Name | Type | Description |
|---|---|---|
totalOrders | integer | |
totalRevenue | integer | |
totalProducts | integer | |
totalCustomers | integer | Distinct customers in the period, keyed like the Customers page (user, else shipping email, else phone) |
allTimeCustomers | integer | |
ordersChange | number (float) | |
revenueChange | number (float) | |
conversionRate | number (float) | Orders per product view (%), null when no views were recorded |
totalProfit | integer | Piastres; null when sold lines have no cost price |
profitItemsMissingCost | integer | |
profitRevenueMissingCost | integer |