AlyaPay Documentation
Online Checkout

Backend Integration

API endpoints for creating sessions and verifying payments

Backend Integration

Your backend calls two AlyaPay API endpoints: one to create payment sessions, and one to verify transactions.

Important: Never expose your API key in frontend code. All API calls must be made from your backend.

API Base URLs

Use the appropriate base URL for your environment:

EnvironmentBase URL
Sandboxhttps://sandbox-api.alyapay.com
Productionhttps://api.alyapay.com

Use development URL with test API keys during development, and production URL with live keys when going live.


Endpoint 1: Create Session

Create a payment session for checkout.

POST /api/v1/public/sessions

Headers

X-API-Key: YOUR_API_KEY_HERE
Content-Type: application/json

Request Body

{
  "total": "1799.00",
  "currency": "MAD",
  "items": [
    {
      "id": "PRODUCT_123",
      "name": "Wireless Headphones",
      "price": 1799,
      "quantity": 1
    }
  ]
}

Parameters

FieldTypeRequiredDescription
totalstringYesTotal order amount
currencystringYesCurrency code: MAD
itemsarrayYesArray of order items
items[].idstringYesUnique product identifier
items[].namestringYesProduct name
items[].pricenumberYesUnit price
items[].quantitynumberYesQuantity

Success Response (200 OK)

{
  "session_token": "eyJraWQiOiJzZXNzaW9uLTIwMjUtMDEi...",
  "expires_in": 3600,
  "session_id": "sess_abc123xyz789"
}

Response Fields:

  • session_token - Pass this to your frontend (valid for 1 hour)
  • expires_in - Token lifetime in seconds (3600 = 1 hour)
  • session_id - Session identifier for reference

Error Responses

StatusErrorDescription
400INVALID_AMOUNTAmount must be greater than 0
400INVALID_CURRENCYUnsupported currency code
400INVALID_ITEMSItems array is missing or invalid
400AMOUNT_MISMATCHTotal doesn't match sum of items
401INVALID_API_KEYAPI key is invalid or missing
429RATE_LIMIT_EXCEEDEDToo many requests (max 100 per 15 min)

Endpoint 2: Verify Transaction

Verify transaction status after payment completes.

GET /api/v1/public/transactions/{transaction_id}/status

Headers

X-Session-Token: SESSION_TOKEN // from step 1

URL Parameters

ParameterDescription
transaction_idTransaction ID from payment callback

Success Response (200 OK)

{
  "status": "APPROVED",
  "transaction_id": "c335bbf0-ae49-42e7-9a7e-c1a6888406dd",
  "payment_intent_id": "8d17b9b9-aea9-4c7e-b753-8223938d7de6",
  "amount": 1799.00,
  "currency": "MAD",
  "merchant_name": "Your Store",
  "store_name": "Your Store",
  "customer_phone": "212650296165",
  "created_at": "12/10/25 16:28:21",
  "updated_at": "12/10/25 16:28:21"
}

Response Fields:

  • status - Transaction status (APPROVED, PENDING, or CANCELED)
  • transaction_id - Unique transaction identifier
  • payment_intent_id - Payment intent identifier
  • amount - Transaction amount (number)
  • currency - Currency code (e.g., MAD)
  • merchant_name - Your merchant name
  • store_name - Your store name
  • customer_phone - Customer's phone number
  • created_at - Transaction creation timestamp
  • updated_at - Last update timestamp

Transaction Statuses

StatusDescriptionWhat to Do
APPROVEDPayment successful✅ Complete and ship order
PENDINGPayment not approved❌ Don't fulfill order
CANCELEDPayment not approved❌ Don't fulfill order

Error Responses

StatusErrorDescription
401INVALID_SESSION_TOKENSession token is invalid or expired
404TRANSACTION_NOT_FOUNDTransaction doesn't exist

Webhooks: Transaction Expired & Cancelled

When a transaction is cancelled by the customer or expires (e.g. after 30 minutes), AlyaPay sends a webhook to your backend so you can update order status in real time.

Webhooks require setup: You must provide us with a webhook URL so we can send you events.

Webhook Events

EventWhen It's Sent
transaction.cancelledCustomer cancels the payment
transaction.expiredPayment window expires (e.g. 30 minutes without payment)

Payload Structure

Both webhooks use the same structure. Example for cancelled:

{
  "event": "transaction.cancelled",
  "timestamp": "2026-02-17T14:30:00.000Z",
  "data": {
    "id": "c335bbf0-ae49-42e7-9a7e-c1a6888406dd",
    "vendorReference": "order_123",
    "orderReference": "ORD-456",
    "status": "CANCELED",
    "amount": 1799,
    "currency": "MAD",
    "customerPhone": "212650296165",
    "merchantName": "Your Store",
    "storeName": "Your Store",
    "createdAt": "2026-02-17T14:00:00.000Z"
  }
}

For expired, the only differences are:

  • "event": "transaction.expired"
  • "data.status": "EXPIRED"
  • "data.expiredAt" is present (when the transaction expired)
{
  "event": "transaction.expired",
  "timestamp": "2026-02-17T14:35:00.000Z",
  "data": {
    "id": "c335bbf0-ae49-42e7-9a7e-c1a6888406dd",
    "vendorReference": "order_123",
    "orderReference": "ORD-456",
    "status": "EXPIRED",
    "amount": 1799,
    "currency": "MAD",
    "customerPhone": "212650296165",
    "merchantName": "Your Store",
    "storeName": "Your Store",
    "createdAt": "2026-02-17T14:00:00.000Z",
    "expiredAt": "2026-02-17T14:30:00.000Z"
  }
}

Data Fields

FieldDescription
eventtransaction.cancelled or transaction.expired
timestampWhen the webhook was sent (ISO 8601)
data.idTransaction ID
data.vendorReferenceYour order/transaction reference
data.orderReferenceOrder reference
data.statusCANCELED or EXPIRED
data.amountTransaction amount
data.currencyCurrency code (e.g. MAD)
data.customerPhoneCustomer phone
data.merchantNameMerchant name
data.storeNameStore name
data.createdAtTransaction creation time
data.expiredAt(Only in expired) When the transaction expired

Handling Webhooks

  1. Return 200 OK quickly
    Respond with HTTP 200 as soon as you receive the webhook. Process the payload asynchronously. If you respond slowly or with an error, AlyaPay may retry.

  2. Update your order status

    • On transaction.cancelled: mark the order as cancelled (customer abandoned).
    • On transaction.expired: mark the order as expired (payment window closed).
  3. Match by vendorReference or data.id
    Use data.id (transaction ID) or data.vendorReference to find the corresponding order in your system.

  4. Idempotency
    The same webhook can be sent more than once. Make your handler idempotent: check if you have already processed this transaction before updating the order.

  5. Validate the webhook (optional)
    If you configured a webhook secret when creating your API key, verify the request signature before processing. (See your API key setup for details.)

Transaction Statuses (including webhooks)

StatusDescriptionWhat to Do
APPROVEDPayment successfulComplete and ship order
PENDINGPayment not yet completedDo not fulfill order
CANCELEDCustomer cancelledMark order cancelled; do not fulfill
EXPIREDPayment window expiredMark order expired; do not fulfill

Security Best Practices

1. Store API Key Securely

# Use environment variables
ALYAPAY_API_KEY=sk_live_your_key_here

Never commit API keys to version control or expose them in frontend code.

2. Validate Input

Before creating a session:

  • Verify total is positive
  • Check items array is not empty
  • Ensure total matches sum of items
  • Validate currency is supported

3. Always Verify Transactions

Never trust frontend events alone. Always verify transaction status with the API before fulfilling orders.

❌ Bad: Frontend says "paid" → Ship order
✅ Good: Frontend event → Backend verifies → Ship order

4. Use HTTPS

Always use HTTPS in production to protect API keys and session tokens in transit.

5. Handle Errors

Implement proper error handling:

  • Log errors for debugging
  • Return user-friendly messages
  • Retry on transient failures
  • Monitor for repeated failures

Need Help?

Email support: support@alyapay.com