Skip to main content
The Embed API uses an OTP (one-time password) flow to authenticate customers. This enables verified checkout without requiring the customer to have an existing account.

Authentication Flow

1

Start session

Send the customer’s phone number to receive an OTP code via WhatsApp (with SMS fallback).
2

Verify OTP

Submit the 4-digit code. If the customer exists, they are authenticated immediately. If new, they proceed to registration.
3

Complete registration (new customers only)

Provide name and email to create the customer account.
4

Use token

The returned Sanctum token is used for authenticated checkout endpoints.

Start Authentication

Sends an OTP code to the customer’s phone number via WhatsApp, falling back to SMS if WhatsApp delivery fails.
POST /api/embed/auth/start

Headers

HeaderRequiredDescription
X-Embed-KeyYesYour store’s embed public key
Content-TypeYesapplication/json

Request Body

FieldTypeRequiredDescription
product_idintegerYesProduct ID (must exist and be active)
country_codestringYesPhone country code (e.g., 966, +966, 00966)
phonestringYesPhone number without country code
curl -X POST "https://embed.rmz.gg/api/embed/auth/start" \
  -H "X-Embed-Key: your_embed_public_key" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 42,
    "country_code": "966",
    "phone": "501234567"
  }'

Success Response (200)

{
  "success": true,
  "data": {
    "session_token": "abc123def456...",
    "expires_in": 300,
    "resend_cooldown": 30,
    "masked_phone": "+966 *****4567"
  }
}
FieldTypeDescription
session_tokenstringSession identifier for subsequent auth requests
expires_inintegerSession expiry in seconds (default: 300 = 5 minutes)
resend_cooldownintegerSeconds to wait before requesting a resend (default: 30)
masked_phonestringPartially masked phone number for display

Error Responses

StatusError CodeDescription
403PHONE_BLOCKEDPhone number is blacklisted
429RATE_LIMIT_EXCEEDEDToo many OTP requests (includes retry_after in seconds)
422-Validation error
404-Product not found

Resend OTP

Resend the verification code via SMS. The original code is replaced with a new one.
POST /api/embed/auth/resend

Request Body

FieldTypeRequiredDescription
session_tokenstringYesThe session token from the start response
curl -X POST "https://embed.rmz.gg/api/embed/auth/resend" \
  -H "X-Embed-Key: your_embed_public_key" \
  -H "Content-Type: application/json" \
  -d '{"session_token": "abc123def456..."}'

Success Response (200)

{
  "success": true,
  "data": {
    "message": "Verification code sent via SMS",
    "resend_cooldown": 30
  }
}

Error Responses

StatusError CodeDescription
404-Session not found
400SESSION_EXPIREDSession has expired, start again
400-Session already verified
429COOLDOWN_ACTIVECooldown period active (includes retry_after)
429RATE_LIMIT_EXCEEDEDToo many resend attempts
Resends always go via SMS, not WhatsApp. The verification code is regenerated on each resend, so only the latest code is valid.

Verify OTP

Submit the 4-digit OTP code to verify the customer’s phone number.
POST /api/embed/auth/verify

Request Body

FieldTypeRequiredDescription
session_tokenstringYesThe session token from the start response
codestringYesThe 4-digit verification code
curl -X POST "https://embed.rmz.gg/api/embed/auth/verify" \
  -H "X-Embed-Key: your_embed_public_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session_token": "abc123def456...",
    "code": "1234"
  }'

Success Response - Existing Customer (200)

If the customer already exists in this store (or in another store on the platform), they are authenticated immediately:
{
  "success": true,
  "data": {
    "status": "authenticated",
    "customer": {
      "id": 1234,
      "firstName": "Ahmed",
      "lastName": "Ali",
      "email": "ahmed@example.com",
      "phone": "501234567",
      "country_code": "966"
    },
    "token": "1|abc123xyz..."
  }
}

Success Response - New Customer (200)

If no customer record exists for this phone number, the response indicates registration is needed:
{
  "success": true,
  "data": {
    "status": "needs_registration",
    "session_token": "abc123def456..."
  }
}

Error Responses

StatusError CodeDescription
404-Session not found
400SESSION_EXPIREDSession has expired
400-Session already verified
400INVALID_CODEWrong code (includes remaining_attempts and optional cooldown_seconds)
400MAX_ATTEMPTS_REACHEDToo many failed attempts, request a new code
429COOLDOWN_ACTIVEMust wait before retrying (includes retry_after)
Invalid code response example:
{
  "success": false,
  "message": "Invalid verification code",
  "error_code": "INVALID_CODE",
  "remaining_attempts": 2,
  "cooldown_seconds": null
}
Customers get 3 attempts per OTP code. After exhausting all attempts, they must request a new code via the resend endpoint.

Complete Registration

Register a new customer after successful OTP verification. Only callable when the verify response returned status: "needs_registration".
POST /api/embed/auth/complete

Request Body

FieldTypeRequiredDescription
session_tokenstringYesThe verified session token
firstNamestringYesCustomer first name (max 100 characters)
lastNamestringYesCustomer last name (max 100 characters)
emailstringYesCustomer email address
curl -X POST "https://embed.rmz.gg/api/embed/auth/complete" \
  -H "X-Embed-Key: your_embed_public_key" \
  -H "Content-Type: application/json" \
  -d '{
    "session_token": "abc123def456...",
    "firstName": "Ahmed",
    "lastName": "Ali",
    "email": "ahmed@example.com"
  }'

Success Response (200)

{
  "success": true,
  "data": {
    "customer": {
      "id": 5678,
      "firstName": "Ahmed",
      "lastName": "Ali",
      "email": "ahmed@example.com",
      "phone": "501234567",
      "country_code": "966"
    },
    "token": "1|xyz789abc..."
  }
}

Error Responses

StatusDescription
400Invalid or expired session
400Registration not allowed for this session (already used)
422Validation error (missing fields, invalid email)

Validate Token

Check if a previously saved token is still valid for a specific product. Use this to restore a customer’s session without re-authenticating.
POST /api/embed/auth/validate

Headers

HeaderRequiredDescription
AuthorizationYesBearer <token>
X-Embed-KeyYesYour store’s embed public key

Request Body

FieldTypeRequiredDescription
product_idintegerYesThe product ID to validate the token against
curl -X POST "https://embed.rmz.gg/api/embed/auth/validate" \
  -H "Authorization: Bearer 1|abc123xyz..." \
  -H "X-Embed-Key: your_embed_public_key" \
  -H "Content-Type: application/json" \
  -d '{"product_id": 42}'

Success Response (200)

{
  "success": true,
  "data": {
    "valid": true,
    "customer": {
      "id": 1234,
      "firstName": "Ahmed",
      "lastName": "Ali",
      "email": "ahmed@example.com",
      "phone": "501234567",
      "country_code": "966"
    }
  }
}

Error Responses

StatusDescription
401Invalid or expired token
403Token not valid for this product (customer belongs to a different store)
422Invalid product ID
Store the authentication token in localStorage and call this endpoint when the embed widget loads. If the token is valid, skip the OTP flow entirely and go straight to checkout.