500 lines
18 KiB
Markdown
500 lines
18 KiB
Markdown
---
|
|
title: Marketplace API
|
|
tags: [api, marketplace, reference]
|
|
---
|
|
|
|
# Marketplace API
|
|
|
|
All marketplace endpoints live under `/api/marketplace/*`. The router is composed of several files mounted from `app.ts`:
|
|
|
|
- New controller-pattern routes: [`backend/src/services/marketplace/controllerRoutes.ts`](../../backend/src/services/marketplace/controllerRoutes.ts) (`marketplaceControllerRouter`)
|
|
- Legacy + delivery-code routes: [`backend/src/services/marketplace/routes.ts`](../../backend/src/services/marketplace/routes.ts) (`marketplaceRouter`)
|
|
- Request templates: [`requestTemplateRoutes.ts`](../../backend/src/services/marketplace/requestTemplateRoutes.ts) (`/api/marketplace/request-templates/*`)
|
|
- Shop settings: [`shopSettingsRoutes.ts`](../../backend/src/services/marketplace/shopSettingsRoutes.ts) (`/api/marketplace/shop/*`)
|
|
- Reviews: [`reviewRoutes.ts`](../../backend/src/services/marketplace/reviewRoutes.ts) (`/api/marketplace/reviews/*`)
|
|
|
|
Core models: [[PurchaseRequest]], [[SellerOffer]], [[Category]], [[RequestTemplate]], [[ShopSettings]], [[Review]]. Real-time updates are emitted on the `request-<id>`, `seller-<id>`, `buyer-<id>`, and `sellers`/`buyers` rooms — see [[Socket Events]].
|
|
|
|
## Categories
|
|
|
|
### GET /api/marketplace/categories
|
|
|
|
**Description:** Flat list of all categories.
|
|
**Auth required:** No
|
|
**Response 200:** `{ success: true, data: [Category, ...] }`
|
|
|
|
### GET /api/marketplace/categories/tree
|
|
|
|
**Description:** Nested tree based on `parentId`.
|
|
**Auth required:** No
|
|
|
|
### GET /api/marketplace/categories/:id
|
|
|
|
**Description:** Single category by id.
|
|
**Auth required:** No
|
|
**Errors:** `404` not found.
|
|
|
|
## Sellers
|
|
|
|
### GET /api/marketplace/sellers
|
|
|
|
**Description:** Public seller directory (users with `role: 'seller'`). Includes aggregated stats (completed orders, ratings).
|
|
**Auth required:** No
|
|
|
|
### GET /api/marketplace/request-templates/sellers
|
|
|
|
**Description:** Sellers who currently expose at least one active [[RequestTemplate]] (used by the shop discovery page).
|
|
**Auth required:** No
|
|
|
|
### GET /api/marketplace/request-templates/sellers/:sellerId
|
|
|
|
**Description:** Public shop profile for a seller, including their templates and shop settings.
|
|
**Auth required:** No
|
|
|
|
## Purchase Requests
|
|
|
|
The buyer-facing CRUD plus seller-side workflow endpoints. Model: [[PurchaseRequest]].
|
|
|
|
### POST /api/marketplace/purchase-requests
|
|
|
|
**Description:** Create a purchase request (new controller path).
|
|
**Auth required:** Bearer JWT (buyer)
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
title: string;
|
|
description: string;
|
|
categoryId: string;
|
|
productLink?: string;
|
|
size?: string;
|
|
color?: string;
|
|
quantity?: number; // default 1
|
|
budget?: { min?: number; max?: number; currency: "USD" | "EUR" | "IRR" };
|
|
urgency?: "low" | "medium" | "high";
|
|
deliveryInfo?: {
|
|
deliveryType: "physical" | "online";
|
|
addressId?: string; // when physical
|
|
email?: string; // when online
|
|
};
|
|
preferredSellerIds?: string[];
|
|
attachments?: string[]; // URLs from [[File API]]
|
|
}
|
|
```
|
|
**Response 201:** `{ success, data: { purchaseRequest } }`
|
|
**Side effects:** Emits `new-purchase-request` to the `sellers` room (broadcast).
|
|
**Source:** `marketplaceController.createPurchaseRequest`
|
|
|
|
### POST /api/marketplace/purchase-requests/bulk
|
|
|
|
**Description:** Bulk creation (used by the template checkout flow).
|
|
**Auth required:** Bearer JWT
|
|
**Request body:** `{ items: Array<PurchaseRequestInput> }`
|
|
|
|
### GET /api/marketplace/purchase-requests
|
|
|
|
**Description:** List requests with filters. Buyers see their own; sellers see ones routed to them; admins see all.
|
|
**Auth required:** Bearer JWT
|
|
**Query params:** `status`, `categoryId`, `urgency`, `search`, `page`, `limit`, `sortBy`, `sortOrder`
|
|
|
|
### GET /api/marketplace/purchase-requests/my
|
|
|
|
**Description:** Shortcut for the caller's own purchase requests.
|
|
**Auth required:** Bearer JWT
|
|
|
|
### GET /api/marketplace/purchase-requests/:id
|
|
|
|
**Description:** Single request with populated category and selected offer.
|
|
**Auth required:** No (public read for shareable links)
|
|
**Errors:** `404` not found.
|
|
|
|
### PATCH /api/marketplace/purchase-requests/:id
|
|
|
|
**Description:** Buyer edits draft / pending request fields.
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### PATCH /api/marketplace/purchase-requests/:id/status
|
|
|
|
**Description:** Transition the request status (`draft` → `pending` → `payment` → `processing` → `delivery` → `delivered` → `seller_paid` → `completed`, or `cancelled`).
|
|
**Auth required:** Bearer JWT (owner or admin)
|
|
**Request body:** `{ status: string }`
|
|
**Side effects:** Emits `purchase-request-update` to `request-<id>`.
|
|
|
|
### DELETE /api/marketplace/purchase-requests/:id
|
|
|
|
**Description:** Cancel/delete a request that has no committed payment.
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/workflow-steps
|
|
|
|
**Description:** Returns the ordered workflow steps + current pointer used by the frontend stepper.
|
|
**Auth required:** No
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/payment-status
|
|
|
|
**Description:** Returns the latest payment + escrow state for the request.
|
|
**Auth required:** Bearer JWT
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/sync-payment-status
|
|
|
|
**Description:** Force a re-check against the payment provider ([[Payment API]]).
|
|
**Auth required:** Bearer JWT
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/confirm-payment
|
|
|
|
**Description:** Legacy buyer-confirmation endpoint kept for old clients.
|
|
**Auth required:** Bearer JWT
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/release-payment
|
|
|
|
**Description:** Triggers admin escrow release (mirror of `POST /api/payment/shkeeper/:id/release`).
|
|
**Auth required:** Bearer JWT (admin)
|
|
|
|
### PUT /api/marketplace/purchase-requests/:id/delivery (controller route)
|
|
|
|
**Description:** Seller submits shipping details (carrier, tracking number, expected date).
|
|
**Auth required:** Bearer JWT (selected seller)
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/update-delivery (legacy)
|
|
|
|
**Description:** Older equivalent retained for compatibility.
|
|
|
|
### POST /api/marketplace/requests/:id/start-delivery
|
|
|
|
**Description:** Marks the request as `delivery` and notifies the buyer.
|
|
**Auth required:** Bearer JWT (seller)
|
|
**Side effects:** Emits `purchase-request-update` event.
|
|
|
|
### PATCH /api/marketplace/purchase-requests/:id/confirm-delivery
|
|
|
|
**Description:** Buyer confirms goods received (transitions to `delivered`).
|
|
**Auth required:** Bearer JWT (buyer)
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/final-approval
|
|
|
|
**Description:** Buyer's final approval that releases escrow to the seller.
|
|
**Auth required:** Bearer JWT (buyer)
|
|
|
|
### GET /api/marketplace/buyers/:buyerId/purchase-requests
|
|
|
|
**Description:** Admin/seller view of a buyer's request history.
|
|
**Auth required:** Bearer JWT
|
|
|
|
## Delivery codes
|
|
|
|
Six-digit codes the buyer hands to the seller at handover. Backed by `deliveryService`.
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/delivery-code/generate
|
|
|
|
**Description:** Buyer generates a delivery code. Request must be in `delivery` status.
|
|
**Auth required:** Bearer JWT (buyer)
|
|
**Response 200:** `{ success: true, data: { deliveryCode: "123456" } }`
|
|
**Errors:** `400` wrong status, `403` not buyer, `404` request not found.
|
|
**Side effects:** Emits `delivery-code-generated` on `request-<id>`.
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/delivery-code/verify
|
|
|
|
**Description:** Seller verifies the code. On success the status moves to `delivered`.
|
|
**Auth required:** Bearer JWT (selected seller)
|
|
**Request body:** `{ code: string }` (exactly 6 chars)
|
|
**Errors:** `400` bad code, `403` not the selected seller.
|
|
**Side effects:** Emits `delivery-confirmed` and `buyer-confirmed-delivery`.
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/delivery-code
|
|
|
|
**Description:** Buyer or seller fetches the current code metadata.
|
|
**Auth required:** Bearer JWT
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/delivery-code/status
|
|
|
|
**Description:** Returns `{ isValid, hasDeliveryCode, ... }` so the UI can decide whether to show "regenerate".
|
|
**Auth required:** Bearer JWT
|
|
|
|
## Seller Offers
|
|
|
|
Model: [[SellerOffer]].
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/offers
|
|
|
|
**Description:** Submit an offer against a purchase request.
|
|
**Auth required:** Bearer JWT (seller)
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
price: { amount: number; currency: "USD" | "EUR" | "IRR" };
|
|
deliveryEstimate: { days: number; note?: string };
|
|
notes?: string;
|
|
attachments?: string[];
|
|
}
|
|
```
|
|
**Response 201:** `{ success, data: { offer } }`
|
|
**Side effects:** Emits `new-offer` to `buyer-<buyerId>` and `seller-offer-update` to `seller-<sellerId>`.
|
|
|
|
### PUT /api/marketplace/purchase-requests/:id/offers (legacy)
|
|
|
|
**Description:** Older offer-update endpoint kept for compatibility.
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/offers
|
|
|
|
**Description:** List all offers for a request.
|
|
**Auth required:** No (buyers and prospective sellers compare offers)
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/has-offer
|
|
|
|
**Description:** Returns `{ hasOffer: boolean }` for the caller (seller-side helper).
|
|
**Auth required:** Bearer JWT (seller)
|
|
|
|
### GET /api/marketplace/purchase-requests/:id/offers/:sellerId
|
|
|
|
**Description:** Fetch a specific seller's offer on a request.
|
|
**Auth required:** No
|
|
|
|
### PATCH /api/marketplace/offers/:id
|
|
|
|
**Description:** Seller edits their pending offer (price, delivery estimate, notes).
|
|
**Auth required:** Bearer JWT (offer owner)
|
|
|
|
### DELETE /api/marketplace/offers/:id
|
|
|
|
**Description:** Seller withdraws their offer.
|
|
**Auth required:** Bearer JWT (offer owner)
|
|
|
|
### PUT /api/marketplace/offers/:id/status
|
|
|
|
**Description:** Direct status mutation (admin override / counter-offer states).
|
|
**Auth required:** Bearer JWT
|
|
**Request body:** `{ status: "pending" | "accepted" | "rejected" | "withdrawn" | "countered" }`
|
|
|
|
### POST /api/marketplace/purchase-requests/:id/select-offer
|
|
|
|
**Description:** Buyer selects/accepts an offer; this triggers payment intent creation in [[Payment API]] and rejects all other offers automatically once payment lands.
|
|
**Auth required:** Bearer JWT (buyer)
|
|
**Request body:** `{ offerId: string }`
|
|
**Side effects:**
|
|
- Updates [[PurchaseRequest]] `selectedOfferId`, status moves toward `payment`.
|
|
- Emits `seller-offer-update` to all sellers for the request.
|
|
|
|
### POST /api/marketplace/offers/:id/accept (legacy)
|
|
|
|
**Description:** Older synonym retained for backward compatibility with old clients.
|
|
|
|
### DELETE /api/marketplace/offers/:id (controller route)
|
|
|
|
**Description:** Controller-pattern delete that also notifies the buyer.
|
|
|
|
## Request Templates
|
|
|
|
A [[RequestTemplate]] is a re-usable "shop product" a seller can publish. Buyers convert templates into actual purchase requests via the shareable link, individually or in bulk (cart checkout).
|
|
|
|
### POST /api/marketplace/request-templates
|
|
|
|
**Description:** Create a new template.
|
|
**Auth required:** Bearer JWT (seller)
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
title: string; // 1-200 chars
|
|
description: string; // 1-2000
|
|
categoryId: string; // MongoId
|
|
productLink?: string; // valid URL
|
|
size?: string; // <=100
|
|
color?: string; // <=100
|
|
quantity?: number; // 1-10000
|
|
budget?: { min?: number; max?: number; currency: "USD" | "EUR" | "IRR" };
|
|
urgency?: "low" | "medium" | "high";
|
|
deliveryInfo?: { deliveryType: "physical" | "online"; email?: string };
|
|
maxUsage?: number | null; // 0/null = unlimited
|
|
expiresAt?: string | null; // ISO date
|
|
images?: string[]; // URLs from [[File API]]
|
|
}
|
|
```
|
|
**Response 201:** `{ data: { template } }` with a generated `shareableLink`.
|
|
|
|
### GET /api/marketplace/request-templates
|
|
|
|
**Description:** Paginated list of the caller's templates.
|
|
**Auth required:** Bearer JWT (seller)
|
|
**Query params:** `page`, `limit` (1-100), `isActive`, `categoryId`, `search`
|
|
|
|
### GET /api/marketplace/request-templates/stats
|
|
|
|
**Description:** Aggregate counts of the caller's templates (active, expired, usage).
|
|
**Auth required:** Bearer JWT (seller)
|
|
|
|
### GET /api/marketplace/request-templates/:id
|
|
|
|
**Description:** Full template by id (owner view).
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### PUT /api/marketplace/request-templates/:id
|
|
|
|
**Description:** Update the template. Same body as create.
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### DELETE /api/marketplace/request-templates/:id
|
|
|
|
**Description:** Delete a template.
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### PATCH /api/marketplace/request-templates/:id/toggle-status
|
|
|
|
**Description:** Toggle `isActive`.
|
|
**Auth required:** Bearer JWT (owner)
|
|
|
|
### GET /api/marketplace/request-templates/public/:shareableLink
|
|
|
|
**Description:** Public read of a template via its shareable slug. Used by the shop preview page.
|
|
**Auth required:** No
|
|
**Errors:** `404` link not found or template inactive/expired.
|
|
|
|
### POST /api/marketplace/request-templates/:shareableLink/convert
|
|
|
|
**Description:** Buyer converts the template into a real [[PurchaseRequest]].
|
|
**Auth required:** Bearer JWT (buyer)
|
|
**Request body:** Overrides (quantity, address, etc.)
|
|
**Response 201:** `{ data: { purchaseRequest } }`
|
|
|
|
### POST /api/marketplace/request-templates/batch-convert
|
|
|
|
**Description:** Convert several templates at once (cart checkout).
|
|
**Auth required:** Bearer JWT (buyer)
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
items: Array<{
|
|
shareableLink: string;
|
|
quantity: number; // 1-100
|
|
sellerId: string; // MongoId
|
|
}>;
|
|
status?: "pending" | "pending_payment" | "active";
|
|
}
|
|
```
|
|
|
|
### POST /api/marketplace/request-templates/complete-payment
|
|
|
|
**Description:** Marks the requests created by `batch-convert` as paid (called after a successful checkout).
|
|
**Auth required:** Bearer JWT
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
requestIds: string[]; // 1+ MongoIds
|
|
newStatus?: "pending" | "active" | "processing";
|
|
paymentData?: Record<string, unknown>;
|
|
}
|
|
```
|
|
|
|
## Shop Settings
|
|
|
|
Per-seller storefront preferences. Model: [[ShopSettings]].
|
|
|
|
### GET /api/marketplace/shop/settings/:sellerId
|
|
|
|
**Description:** Public shop settings for the given seller (used by the shop landing page).
|
|
**Auth required:** No
|
|
**Response 200:** `{ data: ShopSettings }`
|
|
|
|
### GET /api/marketplace/shop/settings
|
|
|
|
**Description:** The authenticated seller's own settings.
|
|
**Auth required:** Bearer JWT (seller)
|
|
|
|
### PUT /api/marketplace/shop/settings
|
|
|
|
**Description:** Update shop settings (banner, bio, policies, `allowSellerReviews`, `allowTemplateReviews`, ...).
|
|
**Auth required:** Bearer JWT (seller)
|
|
|
|
## Reviews
|
|
|
|
Model: [[Review]]. Reviews can target a seller or a template. Subject must be `seller` or `template`.
|
|
|
|
### GET /api/marketplace/reviews/:subjectType/:subjectId
|
|
|
|
**Description:** Published reviews + aggregate stats. Honours `allowSellerReviews` / `allowTemplateReviews` from [[ShopSettings]].
|
|
**Auth required:** No
|
|
**Query params:** `page` (default 1), `limit` (default 10)
|
|
**Response 200:**
|
|
```json
|
|
{
|
|
"data": [Review, ...],
|
|
"pagination": { "page": 1, "limit": 10, "total": 42, "pages": 5 },
|
|
"stats": { "count": 42, "avg": 4.6, "one": 1, "two": 0, "three": 3, "four": 10, "five": 28 }
|
|
}
|
|
```
|
|
**Errors:** `400` bad subjectType / invalid id, `403` reviews disabled by seller.
|
|
|
|
### GET /api/marketplace/reviews/:subjectType/:subjectId/summary
|
|
|
|
**Description:** Stats only (no review list).
|
|
**Auth required:** No
|
|
|
|
### POST /api/marketplace/reviews
|
|
|
|
**Description:** Submit a review. The server computes `isVerifiedBuyer` when `purchaseRequestId` is given and the request is in a terminal state (`delivery`, `delivered`, `seller_paid`, `completed`).
|
|
**Auth required:** Bearer JWT
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
subjectType: "seller" | "template";
|
|
subjectId: string;
|
|
rating: 1 | 2 | 3 | 4 | 5;
|
|
comment?: string;
|
|
purchaseRequestId?: string;
|
|
}
|
|
```
|
|
**Errors:** `400` validation, `403` reviews disabled, `404` template not found, `409` duplicate review.
|
|
**Response 201:** `{ data: Review, stats: { ... } }`
|
|
|
|
## Payments (legacy under marketplace)
|
|
|
|
These routes are duplicates of the main [[Payment API]] kept under `/api/marketplace/payments/*` for backward compatibility with the early frontend. Prefer the canonical endpoints.
|
|
|
|
### POST /api/marketplace/payments
|
|
### GET /api/marketplace/payments
|
|
### GET /api/marketplace/payments/:paymentId
|
|
### PATCH /api/marketplace/payments/:paymentId
|
|
|
|
See [[Payment API]] for the canonical descriptions.
|
|
|
|
## Verify Web3 payment (legacy)
|
|
|
|
### POST /api/marketplace/payments/verify
|
|
|
|
**Description:** Legacy Web3 verification endpoint that records a transaction and moves the purchase request to `processing`. Modern flows use `POST /api/payment/shkeeper/confirm-transaction` instead.
|
|
**Auth required:** Bearer JWT
|
|
**Request body:**
|
|
```ts
|
|
{
|
|
purchaseRequestId: string;
|
|
sellerOfferId: string;
|
|
buyerId: string;
|
|
sellerId: string;
|
|
amount: number;
|
|
currency: "USDT" | string;
|
|
paymentHash: string;
|
|
paymentMethod?: string;
|
|
token?: string;
|
|
network?: string;
|
|
escrowWalletAddress?: string;
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
```
|
|
**Side effects:** Creates a [[Payment]] record, updates [[PurchaseRequest]] status, emits `payment-received` to `user-<sellerId>`.
|
|
|
|
## Real-time events
|
|
|
|
Most marketplace mutations fan out via `global.io` to the rooms below — see [[Socket Events]] for payloads:
|
|
|
|
- `purchase-request-update` → `request-<id>`
|
|
- `new-purchase-request` → `sellers`
|
|
- `new-offer` → `buyer-<buyerId>`
|
|
- `seller-offer-update` → `seller-<sellerId>` (and global on payment confirm)
|
|
- `delivery-code-generated` / `delivery-confirmed` / `delivery-update` → `request-<id>`
|
|
- `request-cancelled` → `user-<buyerId>`, `user-<sellerId>`
|
|
- `transaction-completed` → `user-<buyerId>`, `user-<sellerId>`
|
|
|
|
## Related
|
|
|
|
- [[Purchase Request Flow]]
|
|
- [[Seller Offer Flow]]
|
|
- [[Template Checkout Flow]]
|
|
- [[Delivery Code Flow]]
|