Submit Purchase Transaction
Submit a customer purchase transaction from your Point of Sale system to GrandShift. When a customer completes a purchase at your store and provides their registered phone number, use this endpoint to submit the transaction details.
Development Environment
For testing and development, prepend the base URL:
https://dev.api.grandshifts.comPOST
/pos/v1/invoicesWhat This Endpoint Does
When you submit a transaction, the system will:
- Validate the transaction details (amounts, VAT, customer)
- Automatically approve the invoice
- Calculate and credit cashback rewards to the customer's GrandShift wallet
- Return the invoice status and cashback amount
Important Notes
Validation Rules (Strict)
- Invoice date must be today (transactions must be submitted on the same day)
- Customer must be registered in GrandShift using the provided phone number
- VAT must be exactly 15% of the subtotal amount
- Grand total must equal subtotal + VAT
- Only SAR currency is supported
- Use the
x-idempotency-keyheader to safely retry failed requests
Headers
| Property | Type | Description |
|---|---|---|
x-api-keyRequired | string | Your PoS API key for authentication. |
x-idempotency-key | string | Optional unique identifier to prevent duplicate transactions. Use the same key when retrying failed requests. |
Request Body
| Property | Type | Description |
|---|---|---|
invoiceNumberRequired | string | Unique invoice number from the PoS system. Example: INV-2024-001234 |
invoiceDateRequired | string | Invoice date in ISO 8601 format. Must be today's date. Example: 2024-01-15T10:30:00Z |
totalAmountRequired | number | Total amount before VAT. Must be at least 1 SAR. Example: 850 |
vatRequired | number | VAT amount. Must be exactly 15% of totalAmount. Example: 127.5 |
grandTotalRequired | number | Grand total including VAT. Must equal totalAmount + vat. Example: 977.5 |
currencyRequired | string | Currency code (ISO 4217). Only SAR is supported. Default: SAR |
customerIdentifierRequired | string | Customer phone number registered in GrandShift (shifter account). This is the primary identifier used to lookup the customer and credit their cashback. Example: +966512345678 |
invoiceAttachmentUrl | string | URL to download the receipt/invoice attachment. Example: https://pos.example.com/receipts/INV-2024-001234.pdf |
metadata | object | Additional metadata from the PoS system. Example: { "terminalId": "T001", "cashierId": "C123" } |
Request Example
{
"invoiceNumber": "INV-2024-001234",
"invoiceDate": "2024-01-15T10:30:00Z",
"totalAmount": 850,
"vat": 127.5,
"grandTotal": 977.5,
"currency": "SAR",
"customerIdentifier": "+966512345678",
"invoiceAttachmentUrl": "https://pos.example.com/receipts/INV-2024-001234.pdf",
"metadata": {
"terminalId": "T001",
"cashierId": "C123",
"transactionType": "SALE"
}
}Example Request
cURL
curl -X 'POST' \
'https://dev.api.grandshifts.com/pos/v1/invoices' \
-H 'accept: application/json' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'x-idempotency-key: unique-request-id-123' \
-H 'Content-Type: application/json' \
-d '{
"invoiceNumber": "INV-2024-001234",
"invoiceDate": "2024-01-15T10:30:00Z",
"totalAmount": 850,
"vat": 127.5,
"grandTotal": 977.5,
"currency": "SAR",
"customerIdentifier": "+966512345678"
}'Response Schema
| Property | Type | Description |
|---|---|---|
invoiceIdRequired | number | Internal invoice ID in GrandShift system. Example: 12345 |
invoiceNumberRequired | string | Invoice number from the PoS system. |
statusRequired | string | Current status of the invoice. Enum: PENDING, APPROVED, REJECTED, PAID, REFUNDED, CANCELLED, CASHBACK_PROCESSED |
totalAmountRequired | number | Total amount before VAT. |
vatRequired | number | VAT amount. |
grandTotalRequired | number | Grand total including VAT. |
currencyRequired | string | Currency code. |
vendorCashbackAmount | number | Cashback amount for the customer (if calculated). |
createdAtRequired | string | Timestamp when the invoice was created in GrandShift. |
cashbackProcessedAt | string | Timestamp when cashback was processed. |
Success Response (201 Created)
Transaction submitted successfully. Cashback has been credited to customer.
Response
{
"invoiceId": 12345,
"invoiceNumber": "INV-2024-001234",
"status": "APPROVED",
"totalAmount": 850,
"vat": 127.5,
"grandTotal": 977.5,
"currency": "SAR",
"vendorCashbackAmount": 48.88,
"createdAt": "2024-01-15T10:30:00Z",
"cashbackProcessedAt": "2024-01-15T10:30:05Z"
}Error Responses
401Unauthorized
Invalid or missing API key.
429Too Many Requests
Rate limit exceeded.
Detailed Error Examples
400Invoice Date Mismatch
{
"statusCode": 400,
"message": "Invoice date must be today (2025-12-07). Received: 2024-12-07",
"error": "Bad Request"
}400Customer Not Found
{
"statusCode": 400,
"message": "Customer not found with identifier: +966512345678. Please ensure the customer is registered in the GrandShift system.",
"error": "Bad Request"
}400Invalid Currency
{
"statusCode": 400,
"message": ["Currency must be SAR"],
"error": "Bad Request"
}400Invalid Amount (Less than 1)
{
"statusCode": 400,
"message": ["totalAmount must not be less than 1"],
"error": "Bad Request"
}400Invalid VAT (Not 15%)
{
"statusCode": 400,
"message": ["VAT must be exactly 15% of total amount"],
"error": "Bad Request"
}400Invalid Grand Total
{
"statusCode": 400,
"message": ["Grand total must equal totalAmount + vat"],
"error": "Bad Request"
}400Insufficient Vendor Balance
{
"statusCode": 400,
"message": "Insufficient balance or wallet not eligible for cashback. Current balance: 43624.5, Required: 50000, Wallet active: true",
"error": "Bad Request"
}409Duplicate Invoice Number
{
"statusCode": 409,
"message": "Active invoice with number \"INV-2024-005555\" already exists for this branch",
"error": "Conflict"
}