# Mobile REST API

## Customer profile completion — 2026-08-16

`PUT /api/mobile/customers/{customer}/profile` lets the owning salesman or operations user update contact, location, legal/VAT, cheque metadata and notes. It does not accept authoritative lifecycle, account type or approved financial controls. `POST /api/mobile/customer-applications/{customer}/documents` accepts approved customers and optional `expires_at`, preserving private version history. Customer payloads expose deterministic `profile_complete` / `profile_missing`. Approved customers are ON_ACCOUNT; `invoice_type` remains an explicit per-order `on_account` or `cash` choice and defaults to ON_ACCOUNT.

## Checkout product identity and preflight — 2026-08-16

`product_id` always means the stable master `products.id`. Catalog membership IDs remain explicit as `source_catalog_item_id` and must never be sent as `product_id`. Active Main/Clearance membership and current physical van stock may sell a discontinued/stop-production master product; the selected source still controls price and quantity validation.

`POST /api/mobile/orders/preflight` checks the customer, invoice type, master mapping, current source, price, and availability without writing an order. Failures use `code: checkout_validation_failed` and structured SKU/name/reason issues; internal numeric IDs are not exposed in the salesperson message.

## Stock Replenishment API

Both `/api/mobile` and `/api/v1/mobile` expose list/create/show/update, submit, approve, needs-changes, reject, preparation start/finish, release, return-to-warehouse, dispatch, receive, Request/Preparation/Receiving PDFs and protected attachments under `stock-requests`. Receiving evidence is bound to the exact request item, receipt and receipt item. Laravel enforces ownership, roles, transitions, quantity bounds, variance reasons and idempotency; attachment downloads never expose public paths.

Explicit QA records are visible only to their `qa_owner_user_id` and operations managers. The same restriction is applied to catalog search, barcode lookup, customer selection, orders, Returns product search and Stock Replenishment. Public catalog routes exclude all QA products.

## Customer onboarding and pricing

New authenticated actions: `POST /customer-applications`, `PUT /customer-applications/{customer}`, `POST /customer-applications/{customer}/submit`, document upload/authorized stream, allowed territories, duplicate warnings, and `GET /pricing-config`. Order creation accepts `invoice_type`; Laravel enforces approval, active status, account eligibility, maximum order, cash discount, clearance exclusion and VAT-inclusive snapshots. `GET /orders?customer_id=…` now validates and applies the customer filter.

Base URL:

https://catalog.snyt.xyz/api

## Authentication

The mobile app uses Bearer token authentication.

After login, Flutter must send:

Authorization: Bearer MOBILE_TOKEN
Accept: application/json

## POST /api/mobile/login

Login salesman or admin account.

Request:

{
  "email": "salesman@example.com",
  "password": "password"
}

Response:

{
  "success": true,
  "message": "Login successful.",
  "token_type": "Bearer",
  "token": "TOKEN_HERE",
  "user": {
    "id": 1,
    "name": "Abdallah",
    "email": "email@example.com",
    "role": "salesman"
  }
}

## GET /api/mobile/me

Returns logged-in mobile user.

## POST /api/mobile/logout

Deletes the current mobile token.

## GET /api/mobile/dashboard

Returns salesman dashboard data.

## GET /api/mobile/boxes

Returns boxes owned by the logged-in salesman.

## GET /api/mobile/boxes/{id}

Returns one box.

## GET /api/mobile/boxes/{id}/items

Returns products inside one box.

## GET /api/mobile/products/barcode/{barcode}

Finds a product by barcode, prioritizing current salesman's van stock.





curl -X GET https://catalog.snyt.xyz/api/mobile/me \
  -H "Accept: application/json" \
  -H "Authorization: Bearer XKcpHhyITKxcbBGbhd8zZl917ZXlId83Kr9dQLUPMQ7akUNFEe79RArkWmCagwb86X6wqWoVbF8uMXNx"




curl -X GET https://catalog.snyt.xyz/api/mobile/dashboard \
  -H "Accept: application/json" \
  -H "Authorization: Bearer XKcpHhyITKxcbBGbhd8zZl917ZXlId83Kr9dQLUPMQ7akUNFEe79RArkWmCagwb86X6wqWoVbF8uMXNx"
## GET /api/mobile/van-stock

Returns the logged-in salesman's van stock items.

Optional query:

search=SKU_OR_BARCODE_OR_NAME

Example:

/api/mobile/van-stock?search=charger

## Update - /api/mobile/van-stock

The endpoint now:

- Groups duplicated van stock rows by product or SKU.
- Sums quantities for repeated products.
- Returns product image URL.
- Returns meta data including salesman name and van name.

## Mobile Inventory Check API

### GET /api/mobile/inventory-check

Returns current inventory check status, latest van stock import, progress summary, and items.

### POST /api/mobile/inventory-check/start

Starts a new inventory check for the logged-in salesman.

If another check is open, it is closed automatically.

### POST /api/mobile/inventory-check/mark

Marks one item.

Request:

{
  "van_stock_item_id": 1,
  "status": "correct",
  "counted_qty": 10,
  "note": "optional"
}

Allowed statuses:

- correct
- wrong
- missing
- unchecked

### POST /api/mobile/inventory-check/finish

Completes the open inventory check.

<!-- SNYT_API_BASELINE_START -->

## Current Mobile API Baseline - 2026-08-08

Laravel registers the same protected mobile route group under both prefixes:

```text
/api/mobile/...
/api/v1/mobile/...
```

Login is rate limited. Protected endpoints require the mobile Bearer token.

### Authentication

```text
POST   /api/mobile/login
GET    /api/mobile/me
POST   /api/mobile/logout
```

### Dashboard / Manager

```text
GET    /api/mobile/dashboard
GET    /api/mobile/manager/dashboard
GET    /api/mobile/manager/team
```

### Chat

```text
GET    /api/mobile/chat/contacts
GET    /api/mobile/chat/conversations
POST   /api/mobile/chat/conversations
GET    /api/mobile/chat/conversations/{conversation}/messages
POST   /api/mobile/chat/conversations/{conversation}/messages
POST   /api/mobile/chat/conversations/{conversation}/read
```

### Smart Imports

```text
POST   /api/mobile/smart-imports/analyze
GET    /api/mobile/smart-imports/{session}
POST   /api/mobile/smart-imports/{session}/commit
```

### Daily Sales Report

```text
GET    /api/mobile/reports/daily-sales
POST   /api/mobile/reports/daily-sales/entry
POST   /api/mobile/reports/daily-sales/submit
GET    /api/mobile/reports/daily-sales/pdf
```

### Van Stock / Catalogs / Products

```text
GET    /api/mobile/van-stock
GET    /api/mobile/catalogs/all/products
GET    /api/mobile/catalogs/main/products
GET    /api/mobile/catalogs/clearance/products
GET    /api/mobile/products/barcode/{barcode}
POST   /api/mobile/products/{product}/photos
```

### Boxes / Inventory Check

```text
GET    /api/mobile/boxes
GET    /api/mobile/boxes/{box}
GET    /api/mobile/boxes/{box}/items
GET    /api/mobile/inventory-check
POST   /api/mobile/inventory-check/start
POST   /api/mobile/inventory-check/mark
POST   /api/mobile/inventory-check/finish
```

### Customers

```text
GET    /api/mobile/customers
POST   /api/mobile/customers
GET    /api/mobile/customers/{customer}
PUT    /api/mobile/customers/{customer}/location
```

### Orders

```text
GET    /api/mobile/orders
POST   /api/mobile/orders
GET    /api/mobile/orders/{order}
GET    /api/mobile/orders/{order}/pdf
POST   /api/mobile/orders/{order}/confirm
POST   /api/mobile/orders/{order}/cancel
POST   /api/mobile/orders/{order}/deliver
```

### Sales Tools / Devices / Routes

```text
GET    /api/mobile/sales-tools/visits
POST   /api/mobile/sales-tools/visits
GET    /api/mobile/sales-tools/goals
PUT    /api/mobile/sales-tools/goals
GET    /api/mobile/sales-tools/favorites
POST   /api/mobile/sales-tools/favorites/{product}
GET    /api/mobile/sales-tools/notifications
POST   /api/mobile/sales-tools/notifications/{notification}/read
POST   /api/mobile/devices
DELETE /api/mobile/devices
GET    /api/mobile/routes
POST   /api/mobile/routes/stops/{stop}/complete
```

All endpoints above are also registered under `/api/v1/mobile/...` by the current `routes/api.php` route group.

### Approved Upcoming API Areas

- RMA / Customer Returns
- RMA warehouse handover
- Incremental Warehouse Stock Receiving
- Pricing settings for Cash / On Account
- Invoice pricing preview
- Order revision / invoice editing

<!-- SNYT_API_BASELINE_END -->

<!-- SNYT_RETURNS_RMA_API_V1_START -->
## Returns / RMA API

All endpoints are available under both `/api/mobile` and `/api/v1/mobile` through the shared mobile route group.

### Returns

| Method | Endpoint | Purpose |
|---|---|---|
| GET | `/returns/products/search?q=` | Search product by SKU, barcode, or name and return sellable VAN + RMA quantities |
| GET | `/returns` | List returns visible to the authenticated user |
| POST | `/returns` | Create a return draft |
| GET | `/returns/{return}` | Return details |
| PUT | `/returns/{return}` | Edit a return before handover |
| POST | `/returns/{return}/accounting-review` | Admin/Supervisor pricing and settlement review |
| POST | `/returns/opening-rma` | Reclassify already-counted sellable stock into opening RMA stock |

### RMA Warehouse Handovers

| Method | Endpoint | Purpose |
|---|---|---|
| GET | `/return-handovers` | List handover batches |
| POST | `/return-handovers` | Create a batch from eligible RMA return item IDs |
| GET | `/return-handovers/{handover}` | Handover details |
| POST | `/return-handovers/{handover}/dispatch` | Mark batch handed over / in transit |
| POST | `/return-handovers/{handover}/confirm` | Warehouse received/rejected quantity confirmation |
| GET | `/return-handovers/{handover}/pdf` | Printable A4 warehouse handover PDF |

### Important API Rules

- Laravel remains the stock and financial source of truth.
- A `client_uuid` prevents duplicate return creation on retry.
- Return type is either `resellable` or `rma` and cannot be mixed inside one document.
- Photos are optional and accepted per item.
- Direct exchange can only be used on RMA/defective returns and cannot deduct more replacement quantity than available sellable van stock.
- Handover retries after partial warehouse acceptance use only the remaining rejected/outstanding quantity.
<!-- SNYT_RETURNS_RMA_API_V1_END -->
## Returns API contract update — 2026-08-09

- `POST /api/mobile/return-handovers`: `item_ids` is a required non-empty array of distinct return item IDs.
- `POST /api/mobile/returns`: `customer_id` is required for standard returns.
- `POST /api/mobile/returns/{return}/accounting-review`: all and only the return's items are required; the settlement must cover the approved total; invoice orders must belong to the return customer.
## Explicit Return workflow endpoints

- `POST /api/mobile/returns/{return}/submit`
- `POST /api/mobile/returns/{return}/approve`
- `POST /api/mobile/returns/{return}/reject` (`rejection_reason` required)

Submit is owner-only and freezes editing. Approve/reject require operations-manager access. Duplicate transitions are rejected or safely idempotent; approval cannot add resellable stock twice.
## RMA Stock endpoint

`GET /api/mobile/rma-stock`

Optional query parameters are `search` and, for admin/supervisor users, `salesman_id`. Salesmen are always scoped to their own user ID. Response balances include in-van, prepared, ready, in-transit, and total assigned quantities.
# Import Center web actions

## Stock Receipts API

Authenticated routes under both `/api/mobile` and `/api/v1/mobile` cover list, upload, show, protected document download, request candidates, explicit link, start, idempotent count, item adjustment, finish, and confirm. Ownership is enforced for salesmen. Laravel remains authoritative for matching, variance validation, accepted quantity, and stock posting.

Import Center remains an authenticated admin web workflow; no public/mobile API was added. Its POST actions cover upload, analysis, duplicate resolution, bulk resolution, row update, row skip, and final import. Laravel sessions, CSRF, admin middleware, row locking, and database transactions remain authoritative.
# Daily Work mobile API v1

Authenticated mobile routes under `/api/mobile/daily-work` (also `/api/v1/mobile/daily-work`) provide: current/resumable day, start/end day, start/end breaks, route add/remove/reorder, visit start/end, visit collection, and DWR read/update. Client UUIDs protect Start Day, Start Visit, Break and Collection retries. Laravel enforces ownership and returns 403 for another salesman’s work day, route, visit or customer.

Orders and customer returns created for the same customer during an active visit receive that visit automatically. DWR sales are the current salesman’s confirmed, non-cancelled, non-draft orders whose customer is not QA/test data and whose `confirmed_at` is inside the UAE report date. DWR collections are positive `visit_collections` for the salesman/date, excluding QA/test customers. Collection v1 is operational reporting data, not ledger posting.
