Lookup Subscriptions
GET/subscriptions/lookup
Returns the subscriptions a given end user has with your store, filtered to the ones that currently grant access (status active or trialing) by default.
This is the hot-path endpoint for SaaS paywalls — the typical integration asks “does this user have an active subscription?” on every protected request. The response includes a convenience has_active boolean so you can gate access with a single field check.
Authentication
| Header | Value | Required |
|---|
Authorization | Bearer YOUR_API_TOKEN | Yes |
Accept | application/json | Recommended |
Rate Limit
This endpoint is throttled to 120 requests per minute per API token — higher than the rest of the subscription endpoints because it is intended to be called on every paywalled request. If you expect higher volume, cache results briefly on your side (e.g. 60 seconds per user).
Query Parameters
You must provide at least one of the following user identifiers:
external_customer_id, or
email, or
phone (together with country_code).
If none of these are supplied the request is rejected with a 422.
| Parameter | Type | Required | Description |
|---|
external_customer_id | string (max 191) | Conditional | The merchant’s own user identifier, stored on the subscription at checkout creation time. This is the fastest and most reliable lookup because it is indexed and isolated per store. |
email | email (max 191) | Conditional | Customer email. Matched exactly against the customer record. |
country_code | string (max 5) | Conditional | Country dial code without the + (e.g. 966). A leading + is stripped automatically. Should be paired with phone to be useful. |
phone | string (max 15) | Conditional | Customer phone number (local part only, no country code). |
product_id | integer | No | Restrict results to a single product. Useful when you sell multiple subscription products and only want to check entitlement for one of them. |
include_inactive | boolean | No | Defaults to false. When false, only active and trialing subscriptions are returned (the “currently entitled” view). Set to true to also see paused, past_due, canceled, and expired rows, for example when building a billing history screen. |
The lookup is always scoped to your store — you will never see subscriptions that belong to another merchant, even if the same customer email exists across stores.
Example Requests
Paywall check by external ID (most common)
curl -X GET "https://merchant-api.rmz.gg/shawarma/subscriptions/lookup?external_customer_id=usr_abc123" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Lookup by email, restricted to a specific product
curl -X GET "https://merchant-api.rmz.gg/shawarma/subscriptions/lookup?email=ahmed@example.com&product_id=102" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Lookup by phone, including historical subscriptions
curl -X GET "https://merchant-api.rmz.gg/shawarma/subscriptions/lookup?country_code=966&phone=501234567&include_inactive=1" \
-H "Authorization: Bearer YOUR_API_TOKEN"
Success Response
{
"message": null,
"data": {
"count": 1,
"has_active": true,
"subscriptions": [
{
"id": 501,
"status": "active",
"external_customer_id": "usr_abc123",
"starts_at": "2024-01-01",
"ends_at": "2024-12-31",
"start_date": "2024-01-01",
"end_date": "2024-12-31",
"current_period_start": "2024-01-01T00:00:00.000000Z",
"current_period_end": "2024-12-31T00:00:00.000000Z",
"trial_ends_at": null,
"cancel_at_period_end": false,
"canceled_at": null,
"duration": "annually",
"order_id": 78901,
"auto_renew": true,
"price": {
"amount": 199.99,
"formatted": "١٩٩٫٩٩ ر.س",
"currency": "SAR"
},
"product": {
"id": 102,
"name": "Pro Plan",
"slug": "pro-plan",
"type": "subscription"
},
"variant": {
"id": 15,
"duration": "annually",
"duration_text": "سنه",
"price": 199.99
},
"metadata": {
"external_user_id": "usr_abc123",
"plan": "pro"
},
"features": null,
"is_active": true,
"is_expired": false,
"days_remaining": 276,
"created_at": "2024-01-01T00:00:00.000000Z",
"updated_at": "2024-01-01T00:00:00.000000Z"
}
]
},
"api": "rmz.shawarma",
"timestamp": 1699999999
}
Response Fields
| Field | Type | Description |
|---|
count | integer | Number of subscriptions returned. The endpoint caps results at 50 per call. |
has_active | boolean | true if at least one of the returned rows is active or trialing. Use this as your paywall gate. |
subscriptions | array | Array of subscription objects. Each object has the same shape as Get Subscription, without the payment_method, scheduled_variant, or customer fields (only product and variant relations are preloaded here). |
Empty result
When no subscription matches, the endpoint still returns 200 OK with an empty array — there is no 404:
{
"message": null,
"data": {
"count": 0,
"has_active": false,
"subscriptions": []
},
"api": "rmz.shawarma",
"timestamp": 1699999999
}
Common Integration Pattern
A minimal SaaS paywall middleware:
async function hasActiveSubscription(userId) {
const res = await fetch(
`https://merchant-api.rmz.gg/shawarma/subscriptions/lookup?external_customer_id=${encodeURIComponent(userId)}&product_id=102`,
{ headers: { Authorization: `Bearer ${process.env.RMZ_API_TOKEN}` } }
);
if (!res.ok) {
// Fail closed or fail open depending on your risk tolerance.
// Most paywalls fail closed on 5xx and fail open on network errors.
return false;
}
const { data } = await res.json();
return data.has_active;
}
Pass external_customer_id when you create the checkout session (see Create Checkout Session). That ID is stored on the subscription itself, so the lookup is a direct indexed read instead of a customers table join.
Error Responses
| Code | Description |
|---|
401 | Unauthorized — invalid or missing API token. |
403 | Subscription billing is not enabled for the store (RMZ Plus required). |
422 | Validation error. Returned when no identifier is provided, or when a parameter exceeds its length limit / fails the type check (e.g. email is not a valid email). |
429 | Rate limit exceeded (120 requests per minute per token). |
Example 422 — no identifier supplied
{
"message": "At least one of external_customer_id, email, or phone is required",
"data": null,
"api": "rmz.shawarma",
"timestamp": 1699999999
}
Example 422 — invalid parameter
{
"message": "The given data was invalid.",
"errors": {
"email": ["The email must be a valid email address."]
}
}