Tax (Flat Provider) Module — Vendor surface
Vendor self-service for the flat tax provider — the set of inclusive tax rows (type + rate) that apply uniformly to every line on the vendor's orders. Tax computation is…
Vendor self-service for the flat tax provider — the set of inclusive tax rows (type + rate) that apply uniformly to every line on the vendor's orders. Tax computation is tax-inclusive: line unitPrice is the displayed price and the breakdown is the back-computed split. The whole flat provider is a plugin behind a neutral TAX_PORT; other providers (e.g. region-aware) would expose their own per-vendor surface.
Source:
api-modules/tax-flat/src/controllers/vendor-tax-config.controller.ts.
Conventions
Authentication
Both endpoints require a Better-Auth bearer session with an active vendor.
Authorization: Bearer <session-token>The active vendor is resolved via resolveActiveVendorId(session). Sessions missing an active vendor are rejected with 403 Forbidden. There is no platform RBAC permission — vendor users are not platform staff.
Tenant scoping
Every read and write scopes to the active vendor's id. Config is persisted via VendorSettingsService (audit row per changed key); the controller is the focused UI over the generic vendor.admin.tax settings group.
Response envelope
{
"data": <payload>,
"message": "Success",
"statusCode": 200,
"metadata": { /* optional */ }
}Error envelope
statusCode | errorCode examples |
|---|---|
| 400 | BAD_REQUEST, VALIDATION_ERROR |
| 401 | UNAUTHORIZED |
| 403 | FORBIDDEN (no active vendor) |
| 500 | INTERNAL_SERVER_ERROR |
Domain types
TaxConfigLine
type TaxConfigLine = {
type: string; // e.g. "CGST", "SGST", "VAT" — 1..50 chars trimmed
rate: number; // 0..100 (percent)
};FlatTaxConfigResponse
type FlatTaxConfigResponse = {
taxes: TaxConfigLine[]; // empty array = no tax applied
};Tax config
Base path: /vendor/tax/config.
GET /vendor/tax/config — Current tax rows
Returns the rows shown in the Tax Details panel of the vendor settings UI.
Response 200 — FlatTaxConfigResponse.
{
"data": {
"taxes": [
{ "type": "CGST", "rate": 9 },
{ "type": "SGST", "rate": 9 }
]
},
"message": "Success",
"statusCode": 200
}Empty array (taxes: []) means the vendor has no taxes configured — orders include no tax breakdown.
Errors
| Status | Code | When |
|---|---|---|
| 403 | FORBIDDEN | No active vendor on session |
PATCH /vendor/tax/config — Replace tax rows
Replaces the whole list. Two distinct semantics:
| Body | Effect |
|---|---|
{} (omit taxes) | List untouched; no-op |
{ "taxes": [] } | Explicitly clears the list — no tax applied to future orders |
{ "taxes": [...] } | Replaces the list with the new rows |
Body
{
"taxes": [
{ "type": "CGST", "rate": 9 },
{ "type": "SGST", "rate": 9 }
]
}| Field | Type | Constraints |
|---|---|---|
taxes | TaxConfigLine[]? | Whole-list replace. Send [] to clear; omit to leave untouched |
taxes[].type | string | Trimmed; 1..50 chars |
taxes[].rate | number | >= 0 and <= 100 |
The body is .strict() so unknown top-level keys are rejected at the zod layer.
Response 200 — updated FlatTaxConfigResponse.
Side effects — per-key audit rows via VendorSettingsService. The config lives in the vendor admin.tax settings group (one key per row).
Errors
| Status | Code | When |
|---|---|---|
| 400 | VALIDATION_ERROR | Body fails zod (rate out of range, empty type, unknown top-level key) |
| 403 | FORBIDDEN | No active vendor on session |
Related modules
tax(core) — definestaxConfigLineSchemaand the neutralTAX_PORTinterface. The flat provider is one binding; other providers can expose their own per-vendor surface.settings—vendor.admin.tax.*keys are the underlying store. The generic/vendor/settings/admin/taxendpoints can read the same rows; this controller is the focused PATCH surface.order— linetaxBreakdownandnetAmountare computed using this config at place-order. Seeorder.mdfor the order-line shape.
Shipping Module — Vendor surface
Vendor-facing HTTP surface for shipping configuration (flat customer-charge rate, free-above threshold, enabled providers) and per-sub-order tracking timeline. The vendor charge…
Vendor Module — Vendor-self-service surface
HTTP endpoints for a user applying to become a vendor and inspecting their own application history. This is the "I am not yet a vendor" surface — the caller is a logged-in…