Introduction
The Safqat API lets you manage your data programmatically. It is a REST API that accepts and returns JSON. The base URL is:
https://safqat.ai/api/v1The API is available on the Pro plan. This reference currently covers the Products endpoints. Files cannot be uploaded — pass direct http(s) links for images and media.
Authentication
Authenticate every request with a bearer token created in your Developer settings. Keep it secret — it grants full access to your account's products. The token is shown only once, at creation.
curl https://safqat.ai/api/v1/products \
-H "Authorization: Bearer sqt_live_xxxxxxxxxxxxxxxxxxxx"Requests without a valid token return 401. Tokens for accounts that are not on an active Pro plan return 403.
Rate limits
Each token is limited to 60 requests per minute and 2,000 requests per day. Every response includes RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset (seconds until reset) headers. When you exceed a limit the API responds with 429 and a Retry-After header.
Errors
Errors use conventional HTTP status codes and a consistent JSON body:
{
"error": {
"code": "invalid_field",
"message": "price is required and must be a number >= 0."
}
}Status codes
| Field | Type | Description |
|---|---|---|
| 400 | Bad Request | Invalid JSON, id, or field value. |
| 401 | Unauthorized | Missing or invalid token. |
| 403 | Forbidden | Token's account is not on an active Pro plan. |
| 404 | Not Found | The product does not exist or is not yours. |
| 429 | Too Many Requests | Rate limit exceeded — see Retry-After. |
Pagination
List endpoints are paginated with page (1-based) and pageSize (default 20, max 100) query parameters. The response includes a pagination object.
{
"data": [ /* ... */ ],
"pagination": {
"page": 1,
"pageSize": 20,
"total": 42,
"totalPages": 3,
"hasMore": true
}
}List products
/productsReturns a paginated list of your products, newest first.
Query parameters
| Field | Type | Description |
|---|---|---|
| page | number | Page number, 1-based. Default 1. |
| pageSize | number | Items per page. Default 20, max 100. |
curl "https://safqat.ai/api/v1/products?page=1&pageSize=20" \
-H "Authorization: Bearer $SAFQAT_TOKEN"{
"data": [
{
"id": "6650f1a2c3d4e5f6a7b8c9d0",
"name": "Premium Plan",
"description": "Annual subscription",
"price": 499,
"currency": "SAR",
"paymentPeriod": "yearly",
"imageUrl": "https://cdn.example.com/plan.png",
"mediaUrl": null,
"mediaType": null,
"checkoutUrl": "https://example.com/buy/premium",
"category": "subscriptions",
"isActive": true,
"createdAt": "2026-06-01T10:00:00.000Z"
}
],
"pagination": { "page": 1, "pageSize": 20, "total": 1, "totalPages": 1, "hasMore": false }
}Get a product
/products/{id}Retrieve a single product by id.
curl "https://safqat.ai/api/v1/products/6650f1a2c3d4e5f6a7b8c9d0" \
-H "Authorization: Bearer $SAFQAT_TOKEN"Create a product
/productsCreate a new product. Returns the created product (201).
Body parameters
| Field | Type | Description |
|---|---|---|
| name* | string | Display name of the product. |
| price* | number | Price, must be ≥ 0. |
| description | string | Optional description. |
| currency | string | ISO currency code. Defaults to your agent's currency or SAR. |
| paymentPeriod | enum | one_time | monthly | yearly. Defaults to one_time. |
| imageUrl | string | null | The product's photo (a still image). Direct http(s) link only — no uploads. If mediaUrl is not set, this is the image the agent sends when presenting the product. |
| mediaUrl | string | null | The attachment the agent sends when presenting the product — takes priority over imageUrl. Direct http(s) link only; can be an image, video, or voice file. Set mediaType to match it. |
| mediaType | enum | null | image | video | voice — tells the agent how to deliver mediaUrl. Always set it together with mediaUrl; for video or voice it is required, otherwise the media is not sent. |
| checkoutUrl | string | null | Direct http(s) checkout/purchase link. |
| category | string | Optional category label. |
| isActive | boolean | Whether the product is active. Defaults to true. |
curl -X POST "https://safqat.ai/api/v1/products" \
-H "Authorization: Bearer $SAFQAT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Premium Plan",
"price": 499,
"currency": "SAR",
"paymentPeriod": "yearly",
"imageUrl": "https://cdn.example.com/plan.png",
"checkoutUrl": "https://example.com/buy/premium"
}'Update a product
/products/{id}Update one or more fields of an existing product. Only the fields you send are changed.
Body parameters (all optional)
| Field | Type | Description |
|---|---|---|
| name* | string | Display name of the product. |
| price* | number | Price, must be ≥ 0. |
| description | string | Optional description. |
| currency | string | ISO currency code. Defaults to your agent's currency or SAR. |
| paymentPeriod | enum | one_time | monthly | yearly. Defaults to one_time. |
| imageUrl | string | null | The product's photo (a still image). Direct http(s) link only — no uploads. If mediaUrl is not set, this is the image the agent sends when presenting the product. |
| mediaUrl | string | null | The attachment the agent sends when presenting the product — takes priority over imageUrl. Direct http(s) link only; can be an image, video, or voice file. Set mediaType to match it. |
| mediaType | enum | null | image | video | voice — tells the agent how to deliver mediaUrl. Always set it together with mediaUrl; for video or voice it is required, otherwise the media is not sent. |
| checkoutUrl | string | null | Direct http(s) checkout/purchase link. |
| category | string | Optional category label. |
| isActive | boolean | Whether the product is active. Defaults to true. |
curl -X PATCH "https://safqat.ai/api/v1/products/6650f1a2c3d4e5f6a7b8c9d0" \
-H "Authorization: Bearer $SAFQAT_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "price": 449, "isActive": false }'Delete a product
/products/{id}Permanently delete a product.
curl -X DELETE "https://safqat.ai/api/v1/products/6650f1a2c3d4e5f6a7b8c9d0" \
-H "Authorization: Bearer $SAFQAT_TOKEN"{ "deleted": true, "id": "6650f1a2c3d4e5f6a7b8c9d0" }