🏢 Organization Service
The Organization Service provides a complete REST API for managing organization 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 { organizationService } = services;
const { getMongoClient, createFileStorageDriver } = drivers;
const client = getMongoClient('mongodb://localhost:27017', 'dev');
// Optional but recommended for logo normalization and upload URLs:
// Ensure GOOGLE_APPLICATION_CREDENTIALS points to your GCP service account JSON.
const fileStorageDriver = createFileStorageDriver({
projectId: process.env.GCP_PROJECT_ID!,
bucketName: process.env.GCP_BUCKET_NAME!,
});
express()
.use(
organizationService(
{
organizations: client.collection('organizations'),
identities: client.collection('identities'),
},
{
authSecrets: {
authEncSecret: 'your-encryption-secret',
authSignSecret: 'your-signing-secret',
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001',
},
},
organization: {
roles: {
admin: '100',
member: '001',
owner: '010',
},
},
},
{ fileStorageDriver }
)
)
.use(nodeBlocksErrorMiddleware())
.listen(8089, () => console.log('Server running'));
📋 Endpoint Summary
Basic CRUD Operations
Method | Path | Description | Authorization |
---|---|---|---|
POST | /organizations | Create a new organization | Bearer token required (admin only) |
GET | /organizations/:organizationId | Retrieve an organization by ID | Bearer token required (admin/organization access) |
GET | /organizations | List/filter organizations | Bearer token required (admin only) |
PATCH | /organizations/:organizationId | Update an organization | Bearer token required (admin/owner access) |
DELETE | /organizations/:organizationId | Delete an organization | Bearer token required (admin/owner access) |
File Upload Operations
Method | Path | Description | Authorization |
---|---|---|---|
GET | /organizations/:organizationId/logo-upload-url | Get signed URL to upload organization logo | Bearer token required (admin/owner access) |
Hierarchy Operations
Method | Path | Description | Authorization |
---|---|---|---|
GET | /organizations/:organizationId/descendants | List descendant organizations (optional depth) | Bearer token required (admin/owner access) |
User Management Operations
Method | Path | Description | Authorization |
---|---|---|---|
GET | /organizations/:organizationId/members | List members in an organization | Bearer token required (admin/organization access) |
PATCH | /organizations/:organizationId/members | Add/update members in an organization | Bearer token required (admin/organization access) |
DELETE | /organizations/:organizationId/members/:identityId | Remove member from organization | Bearer token required (admin/organization access) |
GET | /organizations/:organizationId/members/:identityId/role | Get member's role in organization | Bearer token required (admin/organization access) |
GET | /organizations/members/:identityId | Find organizations for a member | Bearer token required (admin/self access) |
🗄️ Entity Schema
The organization entity combines base fields (auto-generated) with organization-specific data:
{
"id": "string",
"createdAt": "string (datetime)",
"updatedAt": "string (datetime)",
"name": "string",
"description": "string",
"contact_email": "string",
"contact_phone": "string",
"address": "object",
"logo": "object or null",
"users": "array"
}
Field Details
Field | Type | Auto-Generated | Required | Description |
---|---|---|---|---|
id | string | ✅ | ✅ | Unique identifier (UUID) |
createdAt | datetime | ✅ | ✅ | Creation timestamp |
updatedAt | datetime | ✅ | ✅ | Last modification timestamp |
name | string | ❌ | ✅ | Organization name (minimum 1 character) |
description | string | ❌ | ✅ | Organization description |
contact_email | string | ❌ | ✅ | Contact email address (email format) |
contact_phone | string | ❌ | ❌ | Contact phone number |
address | object | ❌ | ❌ | Address object (free-form JSON) |
logo | object or null | ❌ | ❌ | Organization logo. Responses: { type, url } ; Requests: { objectId, type } |
users | array | ❌ | ❌ | Array of identities with roles ({id: string, role: string} ) |
📝 Note: 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 Organization
Creates a new organization with the provided information.
Request:
- Method:
POST
- Path:
/organizations
- Headers:
Content-Type: application/json
Authorization: Bearer <token>
x-nb-fingerprint: <device-fingerprint>
- Authorization: Bearer token required (admin only)
Request Body (top-level):
Field | Type | Required | Description |
---|---|---|---|
organization | object | ✅ | Organization payload object (see below) |
ownerId | string | ✅ | Identity ID of the organization owner |
parentId | string | ❌ | Optional parent organization ID |
Organization object fields:
Field | Type | Required | Description |
---|---|---|---|
name | string | ✅ | Organization name (minimum 1 character) |
description | string | ✅ | Organization description |
contact_email | string | ✅ | Contact email address (email format) |
contact_phone | string | ❌ | Contact phone number |
address | object | ❌ | Address object (free-form JSON) |
Response Body:
Field | Type | Description |
---|---|---|
id | string | Unique organization identifier |
name | string | Organization name |
description | string | Organization description |
contact_email | string | Contact email address |
contact_phone | string | Contact phone number |
address | object | Address object (free-form JSON) |
users | array | Array of objects containing user ID and role: {id: string, role: string} |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Enforced automatically (top-level
organization
andownerId
required; insideorganization
,name
,description
, andcontact_email
required; additionalProperties: false) - Route Validators:
- Require authenticated request (bearer token)
- Require admin role
Example Request:
curl -X POST {{host}}/organizations \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <access-token>" \
-d '{
"organization": {
"name": "ACME Corp",
"description": "Leading provider of rocket skates",
"contact_email": "info@acme.test",
"contact_phone": "+1-202-555-0199",
"address": {
"street": "1 Road Runner Way",
"city": "Desert",
"country": "US"
}
},
"ownerId": "identity-123",
"parentId": "org-parent-001"
}'
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "ACME Corp",
"description": "Leading provider of rocket skates",
"contact_email": "info@acme.test",
"contact_phone": "+1-202-555-0199",
"address": {
"street": "1 Road Runner Way",
"city": "Desert",
"country": "US"
},
"users": [
{
"id": "owner-id",
"role": "owner"
}
],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
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 'name'",
"request body must have required property 'description'",
"request body must have required property 'contact_email'",
"request body must have required property 'ownerId'"
]
}
}
When no authorization token is provided:
HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
"error": {
"message": "token could not be verified"
}
}
When database insert operation fails to return an inserted ID:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to create organization"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to create organization"
}
}
2. Get Organization by ID
Retrieves a specific organization by their unique ID.
Request:
- Method:
GET
- Path:
/organizations/:organizationId
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Response Body:
Field | Type | Description |
---|---|---|
id | string | Unique organization identifier |
name | string | Organization name |
description | string | Organization description |
contact_email | string | Contact email address |
contact_phone | string | Contact phone number |
address | object | Address object (free-form JSON) |
users | array | Array of objects containing user ID and role: {id: string, role: string} |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: None
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization membership (owner/admin/member)
Example Request:
curl {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "ACME Corp",
"description": "Leading provider of rocket skates",
"contact_email": "info@acme.test",
"contact_phone": "+1-202-555-0199",
"address": {
"street": "1 Road Runner Way",
"city": "Desert",
"country": "US"
},
"users": [
{
"id": "owner-id",
"role": "owner"
}
],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
}
Error Responses:
When no organization exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to get organization"
}
}
3. List Organizations
Retrieves a list of organizations with optional filtering and pagination.
Request:
- Method:
GET
- Path:
/organizations
- Authorization: Bearer token required (admin only)
Query Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
name | string | ❌ | Filter organizations by name (minimum 1 character) |
description | string | ❌ | Filter organizations by description |
contact_email | string | ❌ | Filter organizations by contact email (email format) |
contact_phone | string | ❌ | Filter organizations by contact phone |
page | number | ❌ | Page number |
limit | number | ❌ | Items per page |
Response Body:
Field | Type | Description |
---|---|---|
id | string | Unique organization identifier |
name | string | Organization name |
description | string | Organization description |
contact_email | string | Contact email address |
contact_phone | string | Contact phone number |
address | object | Address object (free-form JSON) |
users | array | Array of objects containing user ID and role: {id: string, role: string} |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Query parameter validation for name (min length 1), contact_email (email format), contact_phone (string), description (string), and pagination parameters (integers with min/max constraints)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role
Example Requests:
List all organizations:
curl {{host}}/organizations
Filter by name:
curl "{{host}}/organizations?name=ACME Corp"
Filter by contact email:
curl "{{host}}/organizations?contact_email=info@acme.test"
Filter by description:
curl "{{host}}/organizations?description=rocket skates"
Filter by contact phone:
curl "{{host}}/organizations?contact_phone=+1-202-555-0199"
Combine filters:
curl "{{host}}/organizations?name=ACME&contact_email=info@acme.test&page=1&limit=20"
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "ACME Corp",
"description": "Leading provider of rocket skates",
"contact_email": "info@acme.test",
"contact_phone": "+1-202-555-0199",
"address": {
"street": "1 Road Runner Way",
"city": "Desert",
"country": "US"
},
"users": [
{
"id": "owner-id",
"role": "owner"
}
],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T09:41:22.552Z"
},
{
"id": "8fec096b-1bc7-5bfe-c827-3600e8fe2790",
"name": "Wayne Enterprises",
"description": "Gotham's premier technology company",
"contact_email": "contact@wayneenterprises.com",
"users": [
{
"id": "owner-id",
"role": "owner"
}
],
"createdAt": "2024-05-29T10:15:33.441Z",
"updatedAt": "2024-05-29T10:15:33.441Z"
}
]
Error Responses:
When an unexpected error occurs (database connection issues, invalid filter syntax, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to find organizations"
}
}
4. Update Organization
Updates an existing organization with partial data.
Request:
- Method:
PATCH
- Path:
/organizations/:organizationId
- Headers:
Content-Type: application/json
- Authorization: Bearer token required (admin/owner access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Response Body:
Field | Type | Description |
---|---|---|
id | string | Unique organization identifier |
name | string | Updated organization name |
description | string | Updated organization description |
contact_email | string | Updated contact email address |
contact_phone | string | Updated contact phone number |
address | object | Updated address object (free-form JSON) |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
Validation:
- Schema Validation: Enforced automatically (partial updates, all fields optional)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner role
Example Request:
curl -X PATCH {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2 \
-H "Content-Type: application/json" \
-d '{"description": "Updated description for ACME Corp"}'
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"id": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"name": "ACME Corp",
"description": "Updated description for ACME Corp",
"contact_email": "info@acme.test",
"contact_phone": "+1-202-555-0199",
"address": {
"street": "1 Road Runner Way",
"city": "Desert",
"country": "US"
},
"users": [
{
"id": "owner-id",
"role": "owner"
}
],
"createdAt": "2024-05-28T09:41:22.552Z",
"updatedAt": "2024-05-28T14:22:15.789Z"
}
Error Responses:
When request body is missing or empty:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Request body is required"
}
}
When no organization exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When the update operation doesn't modify any data (no changes detected):
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to update organization"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to update organization"
}
}
5. Delete Organization
Permanently deletes an organization from the system.
Request:
- Method:
DELETE
- Path:
/organizations/:organizationId
- Authorization: Bearer token required (admin/owner access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Response Body:
Field | Type | Description |
---|---|---|
No response body | - | Delete endpoint returns no response body on success |
Validation:
- Schema Validation: None
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner role
Example Request:
curl -X DELETE {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2
Success Response:
HTTP/1.1 204 No Content
Error Responses:
When no organization exists with the provided ID:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When an unexpected error occurs (database connection issues, etc.):
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to delete organization"
}
}
👥 User Management Endpoints
6. List Organization Members
Retrieves a list of users associated with an organization.
Request:
- Method:
GET
- Path:
/organizations/:organizationId/members
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Validation:
- Schema Validation: None (GET request)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/members
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"count": 2,
"total": 2,
"value": [
{
"id": "identity-123",
"role": "admin"
},
{
"id": "392157b1-dc7a-4935-a6f9-a2d333b910ea",
"role": "owner"
}
]
}
7. Add/Update Organization Members
Adds new users to an organization or updates existing user roles. Uses upsert logic - if user exists, updates their role; if not, adds them.
Request:
- Method:
PATCH
- Path:
/organizations/:organizationId/members
- Headers:
Content-Type: application/json
,Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Request Body: Array of member objects to add/update:
Field | Type | Required | Description |
---|---|---|---|
id | string | ✅ | Identity identifier |
role | string | ✅ | Member role in the organization |
Validation:
- Schema Validation: Enforced automatically (array with required id and role fields)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl -X PATCH {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/members \
-H "Content-Type: application/json" \
-d '[
{"id": "user123", "role": "admin"},
{"id": "user456", "role": "member"}
]'
Success Response:
HTTP/1.1 204 No Content
Error Responses:
When request body is missing or empty:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Request body non-empty array required"
}
}
When organization doesn't exist:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When database operation fails:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to upsert organization users"
}
}
8. Remove Member from Organization
Removes a specific user from an organization.
Request:
- Method:
DELETE
- Path:
/organizations/:organizationId/members/:identityId
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
identityId | string | ✅ | Unique identity identifier |
Validation:
- Schema Validation: None (DELETE request)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl -X DELETE {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/members/identity-123
Success Response:
HTTP/1.1 204 No Content
Error Responses:
When organization doesn't exist:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When user is not in the organization:
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"message": "Failed to remove user from organization"
}
}
When database operation fails:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to delete organization user"
}
}
9. Get Member Role in Organization
Retrieves the role of a specific user within an organization.
Request:
- Method:
GET
- Path:
/organizations/:organizationId/members/:identityId/role
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
identityId | string | ✅ | Unique identity identifier |
Validation:
- Schema Validation: Path parameter validation (organizationId, identityId required)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl {{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/members/identity-123/role
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"inheritedFrom": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2" ,
"role": "owner"
}
Error Responses:
When organization or user doesn't exist:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When database operation fails:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to get organization user role"
}
}
10. Check Member Existence in Organization
Checks whether a specific user exists within an organization.
Request:
- Method:
GET
- Path:
/organizations/:organizationId/members/check-existence
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/organization access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Unique organization identifier |
Query Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
identityId | string | ✅ | Unique identity identifier to check |
Validation:
- Schema Validation: None (GET request)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl "{{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/members/check-existence?identityId=identity-123"
Success Response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"isUserInOrganization": true
}
Error Responses:
When organization doesn't exist:
HTTP/1.1 404 Not Found
Content-Type: application/json
{
"error": {
"message": "Organization not found"
}
}
When database operation fails:
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"error": {
"message": "Failed to check organization user existence"
}
}
11. Find Organizations for Member
Retrieves all organizations that a specific identity belongs to, including optional inherited roles when requested.
Request:
- Method:
GET
- Path:
/organizations/members/:identityId
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/self access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
identityId | string | ✅ | Unique identity identifier |
Query Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
roles | string | ❌ | Optional comma-separated roles filter (e.g., owner,admin) |
includeInherited | boolean | ❌ | Include inherited roles from descendant organizations |
Validation:
- Schema Validation: Path parameter validation (identityId required) and optional query validation (roles as string; includeInherited as boolean)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or self
Example Request:
curl {{host}}/organizations/members/identity-123
Success Response:
[
{
"member": { "inheritedFrom": null, "role": "owner" },
"organization": {
"id": "org1",
"name": "ACME Corp",
"ancestors": [],
"members": [{ "identityId": "identity-123", "role": "owner" }]
}
},
{
"member": { "inheritedFrom": "org1", "role": "owner" },
"organization": {
"id": "org2",
"ancestors": ["org1"],
"members": [{ "identityId": "identity-123", "role": "member" }]
}
}
]
If User Does Not Exist:
HTTP/1.1 200 OK
Content-Type: application/json
{
"count": 0,
"total": 0,
"value": []
}
12. Get Organization Logo Upload URL
Generates a pre-signed URL for securely uploading an organization logo image. Returns an object ID and a temporary signed URL.
Request:
- Method:
GET
- Path:
/organizations/:organizationId/logo-upload-url
- Headers:
Authorization: Bearer <token>
- Authorization: Bearer token required (admin/owner access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Target organization ID |
Query Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
contentType | string | ✅ | Image MIME type (e.g., image/png ) |
contentLength | number | ✅ | File size in bytes (max 10MB) |
Response Body:
Field | Type | Description |
---|---|---|
objectId | string | Generated storage object ID for the logo |
url | string | Pre-signed URL for uploading the file |
Validation:
- Schema Validation: Uses image upload schema (content type and size constraints)
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner role
Example Request:
curl "{{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/logo-upload-url?contentType=image/png&contentLength=1048576" \
-H "Authorization: Bearer <access-token>"
Success Response:
{
"objectId": "7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2",
"url": "https://storage.googleapis.com/bucket/logos/...&X-Goog-Expires=900&X-Goog-Signature=..."
}
13. List Descendant Organizations
Retrieves all descendant organizations for a given organization, optionally limited by depth.
Request:
- Method:
GET
- Path:
/organizations/:organizationId/descendants
- Headers:
Authorization: Bearer <access-token>
- Authorization: Bearer token required (admin/owner access)
URL Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
organizationId | string | ✅ | Parent organization identifier |
Query Parameters:
Parameter | Type | Required | Description |
---|---|---|---|
depth | number (>=1) | ❌ | Limit descendants by hierarchy depth |
Validation:
- Schema Validation: Path parameter validation (organizationId required); depth must be a positive number when provided
- Route Validators:
- Require authenticated request (bearer token)
- Require admin role or organization owner/admin role
Example Request:
curl "{{host}}/organizations/7edfb95f-0ab6-4adc-a6e1-2a86a2f1e6d2/descendants?depth=2" \
-H "Authorization: Bearer <access-token>"
Success Response:
[
{
"id": "9044d797-384e-4c60-a3b6-1d900ffd8be8",
"name": "ACME Corp",
"description": "Leading provider of rocket skates",
"contact_email": "info@acme.test",
"createdAt": "2025-08-25T07:42:18.643Z",
"updatedAt": "2025-08-25T07:42:18.643Z"
}
]
⚙️ Configuration Options
Service Configuration
interface OrganizationServiceConfiguration {
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
};
};
organization?: {
roles?: {
admin: string; // Admin role identifier
member: string; // Member role identifier
owner: string; // Owner role identifier
};
};
}
Configuration Details
The organization service configuration is organized into logical groups for security, user type management, and organization role 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 encryptionauthSignSecret
: 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"
- Type:
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"
- Type:
regular
: Regular user type identifier- Type:
string
- Description: Custom identifier for regular users
- Use Case: Standard user access permissions
- Example:
"user"
,"member"
,"customer"
- Type:
🏢 Organization Role Settings
organization.roles
- Organization role identifier configuration
- Type:
{ admin?: string; member?: string; owner?: string }
- Description: Custom organization role identifiers for user management within organizations
- Default:
undefined
(uses default role validation) - Child Properties:
admin
: Admin role identifier- Type:
string
- Description: Custom identifier for organization admin role
- Use Case: Administrative permissions within organizations
- Example:
"admin"
,"administrator"
,"manager"
- Type:
member
: Member role identifier- Type:
string
- Description: Custom identifier for organization member role
- Use Case: Standard member permissions within organizations
- Example:
"member"
,"user"
,"employee"
- Type:
owner
: Owner role identifier- Type:
string
- Description: Custom identifier for organization owner role
- Use Case: Full control permissions within organizations
- Example:
"owner"
,"founder"
,"creator"
- Type:
Example Configuration
const organizationConfig = {
authSecrets: {
authEncSecret: process.env.AUTH_ENC_SECRET || 'your-enc-secret',
authSignSecret: process.env.AUTH_SIGN_SECRET || 'your-sign-secret'
},
identity: {
typeIds: {
admin: '100',
guest: '000',
regular: '001'
}
},
organization: {
roles: {
admin: '100',
member: '001',
owner: '010'
}
}
};
🚨 Error Handling
All organization service errors return JSON format with appropriate HTTP status codes:
Common Error Codes
Status | Error Message | Description |
---|---|---|
400 | Validation Error | Invalid request body format or missing required fields |
400 | Request body is required | Missing request body for PATCH operations |
400 | Request body non-empty array required | Missing or empty array for user management operations |
400 | Failed to create organization | Database insert operation failed to return an inserted ID |
400 | Failed to update organization | Update operation doesn't modify any data (no changes detected) |
400 | Failed to remove user from organization | User is not in the organization or removal failed |
401 | token could not be verified | Missing or invalid authorization token |
403 | User is not authorized to access this resource | User lacks required permissions (admin/organization access) |
404 | Organization not found | Organization doesn't exist for the requested operation |
500 | Failed to create organization | Database connection issues or unexpected failures during creation |
500 | Failed to get organization | Database connection issues or unexpected failures during retrieval |
500 | Failed to find organizations | Database connection issues, invalid filter syntax, or unexpected failures during listing |
500 | Failed to update organization | Database connection issues or unexpected failures during update |
500 | Failed to delete organization | Database connection issues or unexpected failures during deletion |
500 | Failed to upsert organization users | Database connection issues or unexpected failures during user management |
500 | Failed to delete organization user | Database connection issues or unexpected failures during user removal |
500 | Failed to get organization user role | Database connection issues or unexpected failures during role retrieval |
500 | Failed to check organization user existence | Database connection issues or unexpected failures during existence check |
500 | Cannot read properties of undefined (reading 'organizations') | Handler implementation bug in find organizations for user endpoint |
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 'name'",
"request body must have required property 'description'",
"request body must have required property 'contact_email'",
"request body must have required property 'ownerId'"
]
}
}
🔗 Related Documentation
- User Service - User management operations
- Authentication Service - Authentication and authorization
- Error Handling - Understanding error patterns
- Schema Component - Data validation concepts
- Custom Service Tutorial - Build your own services