Skip to main content

Seller SOS API Reference

Base URL: https://boxme-sos.pages.dev/api

Tất cả API trả về JSON. Authentication sử dụng Supabase Auth (Bearer token) hoặc demo token.


🏥 Health Check

GET /api/health

// Response 200
{ "status": "ok", "module": "sos-seller", "timestamp": "2026-02-22T00:00:00.000Z" }

🔐 Auth

POST /api/auth/supabase-login

Đăng nhập bằng Supabase Auth.

// Request
{ "email": "admin@boxme.vn", "password": "your_password" }

// Response 200
{
"success": true,
"user": {
"id": 1, "username": "admin", "role": "bod",
"warehouse_id": null, "full_name": "Admin",
"warehouse_name": null, "email": "admin@boxme.vn"
},
"session": {
"access_token": "eyJ...",
"refresh_token": "abc...",
"expires_at": 1708000000
}
}

GET /api/auth/me

Verify session và lấy thông tin user hiện tại.

Authorization: Bearer <access_token>
// Response 200
{
"id": 1, "username": "admin", "role": "bod",
"warehouse_id": null, "full_name": "Admin",
"warehouse_name": null, "email": "admin@boxme.vn",
"employee_code": "BM001", "employee_id": 1
}

POST /api/auth/update-password

Authorization: Bearer <access_token>
// Request
{ "new_password": "new_secure_password" }

// Response 200
{ "success": true, "message": "Mật khẩu đã được cập nhật" }

POST /api/auth/login (Legacy/Demo)

// Request
{ "username": "admin", "password": "admin" }

// Response 200
{ "success": true, "user": { ... }, "token": "demo_token_1_bod" }

🏪 Sellers

GET /api/sellers

Danh sách sellers với filtering và pagination.

Query ParamTypeDefaultDescription
statusstringactiveactive / suspended / terminated
warehouse_idnumberFilter by warehouse
am_idnumberFilter by Account Manager
searchstringSearch seller_code or company_name
pagenumber1Page number
limitnumber20Items per page
// Response 200
{
"data": [
{
"id": 1, "seller_code": "SEL001", "company_name": "Acme Corp",
"contract_type": "B2C", "status": "active",
"am_name": "Nguyen Van A", "warehouse_name": "HN-CG"
}
],
"total": 42, "page": 1, "limit": 20
}

GET /api/sellers/:id

Chi tiết seller (lookup by id hoặc seller_code).

POST /api/sellers

// Request (required: seller_code, company_name)
{
"seller_code": "SEL001",
"company_name": "Acme Corp",
"contract_start_date": "2026-01-01",
"contract_type": "B2C",
"primary_warehouse_id": 1,
"assigned_am_id": 1,
"oms_system_type": "native",
"payment_terms_days": 30,
"metadata": {}
}

// Response 200
{ "success": true, "id": 1 }

PATCH /api/sellers/:id

Cập nhật seller. Chỉ gửi fields cần thay đổi.

// Request
{ "status": "suspended", "payment_terms_days": 15 }
// Response 200
{ "success": true }

GET /api/sellers/:id/exceptions

Danh sách score exceptions của seller.

POST /api/sellers/:id/exceptions

// Request (required: exception_type, adjustment_rule, effective_from)
{
"exception_type": "new_seller_grace",
"score_component_affected": "o_score",
"adjustment_rule": { "set_score": 100 },
"reason": "Seller mới, chưa đủ data O-Score",
"approved_by": "admin",
"effective_from": "2026-01-01",
"effective_to": "2026-03-31"
}
// Response 200
{ "success": true, "id": 5 }

DELETE /api/sellers/:sellerId/exceptions/:exId

Soft-delete exception (is_active = 0).

GET /api/sellers/am/list

Danh sách Account Managers.

POST /api/sellers/am/create

{ "name": "Nguyen Van A", "email": "a@boxme.vn", "employee_id": 10 }

📅 Campaigns

GET /api/campaigns

Query ParamTypeDescription
statusstringupcoming / active / completed / cancelled
typestringmajor_campaign / mini_campaign
page / limitnumberPagination

GET /api/campaigns/:id

Chi tiết campaign (by id or campaign_code).

POST /api/campaigns

// Required: campaign_code, campaign_name, campaign_type, start_date, end_date
{
"campaign_code": "CAMP-2026-02",
"campaign_name": "Valentine Sale",
"campaign_type": "major_campaign",
"start_date": "2026-02-10",
"end_date": "2026-02-16",
"warehouses": ["1", "2"],
"description": "Valentine flash sale",
"created_by": "admin"
}

PATCH /api/campaigns/:id

Update campaign fields.

DELETE /api/campaigns/:id

Cancel campaign (sets status = 'cancelled').

GET /api/campaigns/:id/forecasts

Danh sách seller forecast submissions cho campaign.

GET /api/campaigns/:id/actuals

Danh sách kết quả thực tế (actual results) cho campaign.


📊 SOS Scores

GET /api/sos/sellers/:seller_code/score

Điểm SOS hiện tại của seller (kỳ gần nhất).

// Response 200
{
"seller_code": "SEL001",
"period": "2026-02",
"total_sos": 85.7,
"tier": {
"name": "Gold", "color": "#FFD700",
"benefits": "Priority support, lower surcharge"
},
"components": {
"p_score": { "raw": 85, "weighted": 21.25 },
"o_score": { "raw": 90, "weighted": 18.0 },
"t_score": { "raw": 80, "weighted": 16.0 },
"f_score": { "raw": 100, "weighted": 20.0 },
"i_score": { "raw": 70, "weighted": 10.5 }
},
"trend": { "previous_sos": 82.0, "delta": 3.7, "direction": "improving" },
"top_opportunity": "i_score",
"is_grace_period": false,
"status": "final"
}

GET /api/sos/sellers/:seller_code/score/history

Lịch sử điểm SOS (tối đa 24 kỳ).

Query ParamDescription
fromPeriod bắt đầu (YYYY-MM)
toPeriod kết thúc (YYYY-MM)

GET /api/sos/sellers/:seller_code/enforcement

Kiểm tra enforcement cho WMS — seller có bị block/surcharge không?

// Response 200
{
"seller_code": "SEL001",
"is_blocked": false,
"active_surcharges": [
{ "type": "aging_storage_multiplier", "amount": 150000, "period": "2026-02", "reason": "Inventory aging > 30%" }
]
}

GET /api/sos/tiers

Danh sách tier config (public).

GET /api/sos/monthly

Danh sách monthly scores (admin view).

Query ParamTypeDefaultDescription
periodstringcurrent monthFormat: YYYY-MM
statusstringdraft / under_review / final
am_idnumberFilter by AM
page / limitnumberPagination

PATCH /api/sos/monthly/:id/finalize

Finalize điểm SOS → triggers webhook events.

// Request
{ "reviewed_by": "admin", "notes": "Reviewed and approved" }

// Response 200
{ "success": true }
// → Webhook: seller.score_finalized
// → Webhook: seller.tier_changed (nếu tier thay đổi so với kỳ trước)

POST /api/sos/monthly/calculate

Trigger scoring engine cho tất cả active sellers.

// Request
{ "period": "2026-02" }

// Response 200
{
"period": "2026-02",
"sellers_scored": 42,
"results": [
{ "seller_id": "1", "total_sos": 85.7, "tier": "Gold", "grace": false }
]
}

📋 Appeals

Xem chi tiết tại Appeals & Surcharges.

GET /api/appeals

Query ParamDescription
statuspending / under_review / approved / partially_approved / rejected / expired
periodFormat: YYYY-MM

POST /api/appeals

{
"seller_code": "SEL001",
"period": "2026-02",
"component_appealed": "o_score",
"appeal_reason_type": "system_sync_error",
"description": "OMS sync bị lỗi ngày 2026-02-05",
"evidence_urls": ["https://drive.google.com/file/..."],
"submitted_by_am_id": 1
}

GET /api/appeals/:id

PATCH /api/appeals/:id/review-ops

Ops Head review.

{ "decision": "approve", "notes": "Confirmed OMS issue", "reviewed_by": "ops_head" }

PATCH /api/appeals/:id/review-am

AM Head review (final decision). Có thể kèm score adjustment.

{
"decision": "approve",
"notes": "Approved with adjustment",
"reviewed_by": "am_head",
"score_adjustment": { "o_score_raw_after": 90, "total_sos_after": 87.5 }
}

🔔 Webhooks

Xem chi tiết tại Webhook Integration.

GET /api/webhooks — List subscriptions

POST /api/webhooks — Create subscription

PATCH /api/webhooks/:id — Update subscription

DELETE /api/webhooks/:id — Delete (soft)

GET /api/webhooks/logs — Delivery logs


📈 Dashboard

GET /api/dashboard/stats

Query ParamDescription
periodFormat: YYYY-MM (default: current)
warehouse_idFilter by warehouse
// Response 200
{
"period": "2026-02",
"total_sellers": 42,
"avg_sos": 81.5,
"scored_sellers": 38,
"tier_distribution": [
{ "tier_name": "Gold", "count": 15 },
{ "tier_name": "Silver", "count": 12 }
],
"pending_appeals": 3,
"active_surcharges": 5,
"top_improved": [ { "seller_code": "SEL001", "sos_delta": 8.5, ... } ],
"top_declined": [ { "seller_code": "SEL042", "sos_delta": -5.2, ... } ]
}

💰 Surcharges

GET /api/surcharges

Query ParamDescription
seller_codeFilter by seller
statuspending / applied / waived
periodFormat: YYYY-MM

POST /api/surcharges

{
"seller_code": "SEL001",
"period": "2026-02",
"surcharge_type": "planning_overload",
"amount": 500000,
"trigger_details": { "reason": "No forecast submitted" }
}
// → Webhook: seller.surcharge_created
// → Webhook: seller.order_blocked (nếu type = payment_block)

PATCH /api/surcharges/:id

{ "status": "waived" }

🔄 Data Sync

Xem chi tiết tại Data Sync Integration.

EndpointSourceDescription
POST /api/sync/ordersOMSOrder timing data
POST /api/sync/forecastsOMSForecast submissions
POST /api/sync/campaign-actualsWMS/OMSActual campaign results
POST /api/sync/ticketsHelpdeskTicket SLA metrics
POST /api/sync/paymentsAccountingPayment data
POST /api/sync/inventoryWMSInventory snapshots
POST /api/sync/revenueAccountingAM revenue data

👤 AM Portfolio

GET /api/am/portfolio

Query ParamDescription
periodFormat: YYYY-MM (default: current)

GET /api/am/portfolio/:amId

AM detail + danh sách sellers trong portfolio.

GET /api/am/portfolio/:amId/history

Lịch sử KPI của AM (tối đa 12 kỳ).


⚙️ Configuration

Xem chi tiết tại Configuration Reference.

Tất cả config endpoints follow pattern CRUD chung:

  • GET /api/config/<type> — List active
  • GET /api/config/<type>/:id — Get by id
  • POST /api/config/<type> — Create
  • PUT /api/config/<type>/:id — Update
  • DELETE /api/config/<type>/:id — Soft delete

Available types: score-weights, tiers, p-score, o-score, t-score, f-score, i-score, surcharge, am-bonus-penalty, am-kpi-weight, grace-period, helpdesk


Error Responses

Tất cả errors trả về format:

{ "error": "Human-readable error message" }
Status CodeMeaning
200Success
400Bad Request (missing/invalid params)
401Unauthorized (invalid/expired token)
404Resource not found
500Internal Server Error