メインコンテンツまでスキップ
バージョン: 🚧 Canary

🛒 Order Service

Testing Status

The Order Service provides a complete REST API for managing order entities with CRUD operations. It's built using the Nodeblocks functional composition approach and integrates seamlessly with MongoDB.


🚀 Quickstart

import express from 'express';
import { middlewares, services, drivers } from '@nodeblocks/backend-sdk';

const { nodeBlocksErrorMiddleware } = middlewares;
const { orderService } = services;
const { getMongoClient } = drivers;

const client = getMongoClient('mongodb://localhost:27017', 'dev');

express()
.use(
orderService(
{
orders: client.collection('orders'),
identities: client.collection('identities'),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
}
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));

📋 Endpoint Summary

Order Operations

MethodPathDescriptionAuth Required
POST/ordersCreate a new order✅ Required
GET/orders/:orderIdRetrieve an order by ID✅ Required
GET/ordersList/filter orders✅ Required
PATCH/orders/:orderIdUpdate an order✅ Required
DELETE/orders/:orderIdDelete an order✅ Required

🗄️ Entity Schema

The order entity combines base fields (auto-generated) with complex order-specific data including items array and pricing:

{
"items": [
{
"productId": "string (uuid)",
"quantity": "number",
"price": "number"
}
],
"total": "number",
"subtotal": "number",
"tax": "number",
"currency": "string",
"status": "string",
"identityId": "string (uuid)",
"organizationId": "string (uuid)",
"createdAt": "string (datetime)",
"id": "string",
"updatedAt": "string (datetime)"
}

Field Details

FieldTypeAuto-GeneratedRequiredDescription
itemsarrayArray of order items with product details
totalnumberTotal order amount (minimum 0)
subtotalnumberSubtotal before tax (minimum 0)
taxnumberTax amount (minimum 0)
currencystringCurrency code (e.g., "USD", "EUR")
statusstringOrder status (e.g., "pending", "completed")
identityIdstring (uuid)Identity who placed the order
organizationIdstring (uuid)Organization associated with the order
createdAtdatetimeCreation timestamp
idstringUnique identifier (UUID)
updatedAtdatetimeLast modification timestamp

Items Array Schema

Each item in the items array must contain:

FieldTypeRequiredValidationDescription
productIdstring (uuid)UUID formatProduct identifier
quantitynumberMinimum 1Quantity ordered
pricenumberMinimum 0Price per unit

📝 Note: The schema enforces additionalProperties: false, meaning only defined fields are allowed. Auto-generated fields are set by the service and should not be included in create/update requests.


🔐 Authentication Headers

For all endpoints, include the following headers:

Authorization: Bearer <access_token>
x-nb-fingerprint: <device_fingerprint>

⚠️ Important: The x-nb-fingerprint header is required for all authenticated requests if fingerprint was specified during authorization. Without it, requests will return 401 Unauthorized.


🔧 API Endpoints

1. Create Order

Creates a new order with the provided information including items array and pricing details.

Request:

  • Method: POST
  • Path: /orders
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Request Body:

FieldTypeRequiredDescription
itemsarrayArray of order items (see Items Schema)
totalnumberTotal order amount
identityIdstring (uuid)Identity who placed the order
subtotalnumberSubtotal before tax
taxnumberTax amount
currencystringCurrency code
statusstringOrder status
organizationIdstring (uuid)Organization associated with order

Response Body:

FieldTypeDescription
itemsarrayArray of order items with product details
items[].productIdstringProduct identifier
items[].quantitynumberQuantity ordered
items[].pricenumberPrice per unit
totalnumberTotal order amount
subtotalnumberSubtotal before tax
taxnumberTax amount
currencystringCurrency code
statusstringOrder status
identityIdstringIdentity who placed the order
organizationIdstringOrganization associated with order
createdAtstringCreation timestamp
idstringUnique order identifier
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (items, total, identityId required)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or self (order owner)

Authorization Note: When creating an order, the identityId field in the request body must match the identityId associated with your access token. If you attempt to create an order for a different identity, you will receive a 403 Forbidden error.

Admin users cannot create orders for other users unless the backend validator logic is changed to allow this.

Example Request:

curl -X POST http://localhost:8089/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{
"identityId": "30000000-0000-4000-a000-000000000001",
"items": [
{
"productId": "10000000-0000-4000-a000-000000000001",
"quantity": 2,
"price": 50
},
{
"productId": "10000000-0000-4000-a000-000000000002",
"quantity": 1,
"price": 25
}
],
"subtotal": 125,
"tax": 12.5,
"total": 137.5,
"currency": "USD",
"status": "pending",
"organizationId": "20000000-0000-4000-a000-000000000001"
}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"currency": "USD",
"items": [
{
"productId": "10000000-0000-4000-a000-000000000001",
"quantity": 2,
"price": 50
},
{
"productId": "10000000-0000-4000-a000-000000000002",
"quantity": 1,
"price": 25
}
],
"organizationId": "20000000-0000-4000-a000-000000000001",
"identityId": "30000000-0000-4000-a000-000000000001",
"subtotal": 125,
"tax": 12.5,
"total": 137.5,
"status": "pending",
"createdAt": "2025-07-04T01:59:20.084Z",
"id": "10283907-d41a-4647-a235-18ec63f3369a",
"updatedAt": "2025-07-04T01:59:20.084Z"
}

Error Responses:

When request body is missing required fields:

HTTP/1.1 400 Bad Request
Content-Type: application/json

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'identityId'",
"request body must have required property 'items'"
]
}
}

When authentication fails:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
"error": {
"message": "token could not be verified"
}
}

When authorization fails:

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
"error": {
"message": "User is not authorized to access this order"
}
}

2. Get Order by ID

Retrieves a specific order by its unique ID.

Request:

  • Method: GET
  • Path: /orders/:orderId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

URL Parameters:

ParameterTypeRequiredDescription
orderIdstringUnique order identifier

Response Body:

FieldTypeDescription
itemsarrayArray of order items with product details
items[].productIdstringProduct identifier
items[].quantitynumberQuantity ordered
items[].pricenumberPrice per unit
totalnumberTotal order amount
subtotalnumberSubtotal before tax
taxnumberTax amount
currencystringCurrency code
statusstringOrder status
identityIdstringIdentity who placed the order
organizationIdstringOrganization associated with order
createdAtstringCreation timestamp
idstringUnique order identifier
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: None (GET request)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or order ownership

Example Request:

curl http://localhost:8089/orders/10283907-d41a-4647-a235-18ec63f3369a \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"currency": "USD",
"items": [
{
"productId": "10000000-0000-4000-a000-000000000001",
"quantity": 2,
"price": 50
},
{
"productId": "10000000-0000-4000-a000-000000000002",
"quantity": 1,
"price": 25
}
],
"organizationId": "20000000-0000-4000-a000-000000000001",
"identityId": "30000000-0000-4000-a000-000000000001",
"subtotal": 125,
"tax": 12.5,
"total": 137.5,
"status": "completed",
"createdAt": "2025-07-04T01:59:20.084Z",
"id": "10283907-d41a-4647-a235-18ec63f3369a",
"updatedAt": "2025-07-07T08:11:16.176Z"
}

Error Responses:

When no order exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Order not found"
}
}

3. List Orders

Retrieves a list of orders with optional filtering and pagination.

Request:

  • Method: GET
  • Path: /orders
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

Query Parameters:

ParameterTypeRequiredDescription
currencystringFilter by currency
organizationIdstringFilter by organization
statusstringFilter by status
subtotalnumberFilter by subtotal amount
taxnumberFilter by tax amount
totalnumberFilter by total amount
identityIdstringFilter by identityId
pagenumberPage number for pagination
limitnumberNumber of items per page

Response Body:

FieldTypeDescription
itemsarrayArray of order items with product details
items[].productIdstringProduct identifier
items[].quantitynumberQuantity ordered
items[].pricenumberPrice per unit
totalnumberTotal order amount
subtotalnumberSubtotal before tax
taxnumberTax amount
currencystringCurrency code
statusstringOrder status
identityIdstringIdentity who placed the order
organizationIdstringOrganization associated with order
createdAtstringCreation timestamp
idstringUnique order identifier
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: None (GET request)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or self

Example Requests:

List all orders:

curl http://localhost:8089/orders \
-H "Authorization: Bearer <access_token>"

Filter by status:

curl "http://localhost:8089/orders?status=completed" \
-H "Authorization: Bearer <access_token>"

Filter by currency:

curl "http://localhost:8089/orders?currency=USD" \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

[
{
"currency": "USD",
"items": [
{
"productId": "10000000-0000-4000-a000-000000000001",
"quantity": 2,
"price": 50
},
{
"productId": "10000000-0000-4000-a000-000000000002",
"quantity": 1,
"price": 25
}
],
"organizationId": "20000000-0000-4000-a000-000000000001",
"identityId": "30000000-0000-4000-a000-000000000001",
"subtotal": 125,
"tax": 12.5,
"total": 137.5,
"status": "completed",
"createdAt": "2025-07-04T01:59:20.084Z",
"id": "10283907-d41a-4647-a235-18ec63f3369a",
"updatedAt": "2025-07-07T08:11:16.176Z"
}
]

4. Update Order

Updates an existing order with partial data.

Request:

  • Method: PATCH
  • Path: /orders/:orderId
  • Headers:
    • Content-Type: application/json
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

URL Parameters:

ParameterTypeRequiredDescription
orderIdstringUnique order identifier

Request Body (all fields optional):

FieldTypeRequiredDescription
itemsarrayArray of order items
totalnumberTotal order amount
subtotalnumberSubtotal before tax
taxnumberTax amount
currencystringCurrency code
statusstringOrder status
identityIdstring (uuid)Identity who placed the order
organizationIdstring (uuid)Organization associated with order

Response Body:

FieldTypeDescription
itemsarrayArray of order items with product details
items[].productIdstringProduct identifier
items[].quantitynumberQuantity ordered
items[].pricenumberPrice per unit
totalnumberUpdated total order amount
subtotalnumberUpdated subtotal before tax
taxnumberUpdated tax amount
currencystringUpdated currency code
statusstringUpdated order status
identityIdstringIdentity who placed the order
organizationIdstringUpdated organization associated with order
createdAtstringCreation timestamp
idstringUnique order identifier
updatedAtstringLast update timestamp

Validation:

  • Schema Validation: Enforced automatically (partial updates, all fields optional)
  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or order ownership

Example Request:

curl -X PATCH http://localhost:8089/orders/10283907-d41a-4647-a235-18ec63f3369a \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access_token>" \
-d '{"status": "completed"}'

Success Response:

HTTP/1.1 200 OK
Content-Type: application/json

{
"currency": "USD",
"items": [
{
"productId": "10000000-0000-4000-a000-000000000001",
"quantity": 2,
"price": 50
},
{
"productId": "10000000-0000-4000-a000-000000000002",
"quantity": 1,
"price": 25
}
],
"organizationId": "20000000-0000-4000-a000-000000000001",
"identityId": "30000000-0000-4000-a000-000000000001",
"subtotal": 125,
"tax": 12.5,
"total": 137.5,
"status": "completed",
"createdAt": "2025-07-04T01:59:20.084Z",
"id": "10283907-d41a-4647-a235-18ec63f3369a",
"updatedAt": "2025-07-07T08:11:16.176Z"
}

Error Responses:

When no order exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Order not found"
}
}

5. Delete Order

Permanently deletes an order from the system.

Request:

  • Method: DELETE
  • Path: /orders/:orderId
  • Headers:
    • Authorization: Bearer <token>
    • x-nb-fingerprint: <device-fingerprint>
  • Authorization: Bearer token required

URL Parameters:

ParameterTypeRequiredDescription
orderIdstringUnique order identifier

Response Body:

FieldTypeDescription
No response body-Delete endpoint returns no response body on success

Validation:

  • Route Validators:
    • Require authenticated request (bearer token)
    • Require admin role or order ownership

Example Request:

curl -X DELETE http://localhost:8089/orders/10283907-d41a-4647-a235-18ec63f3369a \
-H "Authorization: Bearer <access_token>"

Success Response:

HTTP/1.1 204 No Content

Error Responses:

When no order exists with the provided ID:

HTTP/1.1 404 Not Found
Content-Type: application/json

{
"error": {
"message": "Order not found"
}
}

⚙️ Configuration Options

Service Configuration

interface OrderServiceConfiguration {
authSecrets: {
authEncSecret: string; // JWT encryption secret
authSignSecret: string; // JWT signing secret
};
identity?: {
typeIds?: {
admin: string; // Admin user type identifier
guest: string; // Guest user type identifier
regular: string; // Regular user type identifier
};
};
}

Configuration Details

The order service configuration is organized into logical groups for security and user type management.

🔐 Security Settings

authSecrets - JWT token security secrets

  • Type: { authEncSecret: string; authSignSecret: string }
  • Description: Secret keys for JWT encryption and signing (used for token validation)
  • Required: Yes (for production)
  • Child Properties:
    • authEncSecret: Secret key for JWT payload encryption
    • authSignSecret: Secret key for JWT signature verification

👥 User Type Settings

identity.typeIds - User type identifier configuration

  • Type: { admin?: string; guest?: string; regular?: string }
  • Description: Custom user type identifiers for role-based access control
  • Default: undefined (uses default type validation)
  • Child Properties:
    • admin: Admin user type identifier
      • Type: string
      • Description: Custom identifier for admin users
      • Use Case: Role-based access control for administrative operations
      • Example: "admin", "administrator", "superuser"
    • guest: Guest user type identifier
      • Type: string
      • Description: Custom identifier for guest users
      • Use Case: Limited access for unauthenticated or temporary users
      • Example: "guest", "visitor", "anonymous"
    • user: Regular user type identifier
      • Type: string
      • Description: Custom identifier for regular users
      • Use Case: Standard user access permissions
      • Example: "user", "member", "customer"

Example Configuration

const orderConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: 'administrator',
guest: 'visitor',
regular: 'member'
}
}
};

🚨 Error Handling

All order service errors return JSON format with appropriate HTTP status codes:

Common Error Codes

StatusError MessageDescription
400Validation ErrorInvalid request body format or missing required fields
400request body must have required property 'identityId'Missing identityId field in request body
400request body must have required property 'items'Missing items array in request body
400request body must have required property 'total'Missing total field in request body
400request body must NOT have additional propertiesRequest contains unsupported fields
400Failed to create orderDatabase insert operation failed to return an inserted ID
400Failed to update orderUpdate operation doesn't modify any data (no changes detected)
400Failed to delete orderDatabase deletion operation failed
401token could not be verifiedMissing or invalid authorization token
401Authentication failedMissing or invalid authentication token
401Token fails security checkToken security validation failed
403User is not authorized to access this orderUser lacks required permissions (admin/owner access)
403User is not authorized to access this resourceUser lacks required permissions (admin access)
404Order not foundOrder doesn't exist for the requested operation
500Failed to create orderDatabase connection issues or unexpected failures during creation
500Failed to get orderDatabase connection issues or unexpected failures during retrieval
500Failed to find ordersDatabase connection issues, invalid filter syntax, or unexpected failures during listing
500Failed to update orderDatabase connection issues or unexpected failures during update
500Failed to delete orderDatabase connection issues or unexpected failures during deletion

Error Response Format

{
"error": {
"message": "Error message description",
"data": ["Additional error details"]
}
}

Validation Errors include additional details:

{
"error": {
"message": "Validation Error",
"data": [
"request body must have required property 'items'",
"request body must have required property 'total'"
]
}
}