API

Organizations - Branches

Branch management, invitations, and branch creation via token.

Base path: /api/v1/organizations/branches

Used by: owner-booki-web-app · Role: owner, branch-manager
organizationId: From authenticated user's JWT token (no tenant header needed)

Owners manage branches (multiple locations) with branch managers as sub-owners. Branch invites allow branch managers to join via secure tokens.


POST /api/v1/organizations/branches/invite — Send Branch Invite

Auth: Protected (Authorization: Bearer <accessToken>)
Used by: owner-booki-web-app · Role: owner
Description: Send an email invitation to create a branch.

Request

{
  "email": "manager@example.com"
}

Fields:

  • email (string, required): Manager's email

Note: organizationId is read from the owner's JWT token server-side.

Response (200 OK)

{
  "message": "Branch manager invite sent successfully."
}

Error Responses

422 Unprocessable Entity — Invalid email:

{
  "statusCode": 422,
  "message": "\"email\" must be a valid email"
}

cURL Example

curl -X POST http://localhost:4001/api/v1/organizations/branches/invite \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer eyJhbGc..." \
  -d '{
    "email": "manager@example.com"
  }'

GET /api/v1/organizations/branches/invite — List Branch Invites

Auth: Protected (Authorization: Bearer <accessToken>) · branch-manager+
Used by: owner-booki-web-app · Role: owner
Description: List all pending and used branch invites.

Request

Query Parameters (optional):

  • page (number, default: 1)
  • limit (number, default: 10, max: 100)
  • search (string, max 100 chars)
  • sort (string, default: _id)
  • order (string, default: desc): asc or desc
GET /api/v1/organizations/branches/invite?page=1&limit=20

Response (200 OK)

{
  "items": [
    {
      "_id": "507f1f77bcf86cd799439061",
      "organizationId": "507f191e810c19729de860ea",
      "email": "manager@example.com",
      "status": "pending",
      "createdAt": "2026-04-01T10:00:00Z",
      "expiresAt": "2026-04-08T10:00:00Z"
    },
    {
      "_id": "507f1f77bcf86cd799439062",
      "organizationId": "507f191e810c19729de860ea",
      "email": "branch2@example.com",
      "status": "accepted",
      "createdAt": "2026-03-25T14:00:00Z",
      "acceptedAt": "2026-03-26T09:30:00Z"
    }
  ],
  "pages": 1,
  "pageRange": "1-2 of 2"
}

cURL Example

curl -X GET "http://localhost:4001/api/v1/organizations/branches/invite?page=1&limit=20" \
  -H "Authorization: Bearer eyJhbGc..."

GET /api/v1/organizations/branches/invite/token/:token/verify — Verify Invite Token

Auth: Public
Used by: cms-booki-web-app (invite acceptance page) · Role: guest
organizationId: Not required
Description: Verify that an invite token is valid before creating branch.

Request

GET /api/v1/organizations/branches/invite/token/INVITE_ABC123XYZ.../verify

No body required.

Response (200 OK)

{
  "valid": true,
  "invite": {
    "_id": "507f1f77bcf86cd799439061",
    "email": "manager@example.com",
    "organizationId": "507f191e810c19729de860ea",
    "expiresAt": "2026-04-08T10:00:00Z"
  }
}

Error Responses

400 Bad Request — Token expired or invalid:

{
  "statusCode": 400,
  "message": "Invite token is invalid or expired"
}

cURL Example

curl -X GET "http://localhost:4001/api/v1/organizations/branches/invite/token/INVITE_ABC123XYZ.../verify"

POST /api/v1/organizations/branches/token/:token — Create Branch via Token

Auth: Public
Used by: cms-booki-web-app (branch manager signup) · Role: guest
organizationId: Embedded in invite token
Description: Complete branch creation using a valid invite token. Creates the branch and branch manager user.

Request

The token is passed as a URL parameter (:token), not in the request body.

{
  "address": {
    "region": "NCR",
    "province": "Metro Manila",
    "municipalOrCity": "Makati",
    "barangay": "Makati",
    "zip": "1200",
    "street": "Ayala Avenue",
    "address": "456 Business Park Tower"
  },
  "branchManager": {
    "firstName": "Maria",
    "lastName": "Santos",
    "phone": "09177654321",
    "password": "BranchMgrP@ss123"
  }
}

Fields:

  • address (object, required):
    • region, province, municipalOrCity, barangay, zip (required)
    • street, address (optional)
  • branchManager (object, required):
    • firstName, lastName, phone, password (required)
    • middleName (optional)

Response (201 Created)

{ "message": "Branch successfully created." }

Error Responses

400 Bad Request — Weak password:

{
  "statusCode": 400,
  "message": "Password must contain at least one uppercase letter, one lowercase letter, one number, and one special character"
}

400 Bad Request — Token expired:

{
  "statusCode": 400,
  "message": "Invite token is invalid or expired"
}

cURL Example

curl -X POST "http://localhost:4001/api/v1/organizations/branches/token/INVITE_ABC123XYZ..." \
  -H "Content-Type: application/json" \
  -d '{
    "address": {
      "region": "NCR",
      "province": "Metro Manila",
      "municipalOrCity": "Makati",
      "barangay": "Makati",
      "zip": "1200"
    },
    "branchManager": {
      "firstName": "Maria",
      "lastName": "Santos",
      "phone": "09177654321",
      "password": "BranchMgrP@ss123"
    }
  }'

GET /api/v1/organizations/branches — List Branches

Auth: Protected (Authorization: Bearer <accessToken>) · branch-manager+
Used by: owner-booki-web-app · Role: owner, branch-manager
Description: List all branches for the authenticated user's organization.

Request

Query Parameters (optional):

  • page (number, default: 1)
  • limit (number, default: 10, max: 100)
GET /api/v1/organizations/branches?page=1&limit=20

Response (200 OK)

{
  "items": [
    {
      "_id": "507f191e810c19729de860ea",
      "organizationId": "507f191e810c19729de860ea",
      "name": "Main Branch",
      "slug": "main",
      "managerId": "507f1f77bcf86cd799439001",
      "address": {
        "region": "NCR",
        "municipalOrCity": "Quezon City",
        "zip": "1100"
      },
      "status": "ACTIVE",
      "createdAt": "2026-03-15T10:00:00Z"
    },
    {
      "_id": "507f191e810c19729de860eb",
      "organizationId": "507f191e810c19729de860ea",
      "name": "Branch Makati",
      "slug": "makati",
      "managerId": "507f1f77bcf86cd799439071",
      "address": {
        "region": "NCR",
        "municipalOrCity": "Makati",
        "zip": "1200"
      },
      "status": "ACTIVE",
      "createdAt": "2026-04-01T11:00:00Z"
    }
  ],
  "total": 2,
  "page": 1,
  "limit": 20,
  "pages": 1
}

cURL Example

curl -X GET "http://localhost:4001/api/v1/organizations/branches?page=1&limit=20" \
  -H "Authorization: Bearer eyJhbGc..."

PUT /api/v1/organizations/branches/invite/:id/resend — Resend Invite

Auth: Protected (Authorization: Bearer <accessToken>) · branch-manager+
Used by: owner-booki-web-app · Role: owner
Description: Resend an expired or lost branch invite.

Response (200 OK)

{ "message": "Invite resent successfully." }

cURL Example

curl -X PUT "http://localhost:4001/api/v1/organizations/branches/invite/507f1f77bcf86cd799439061/resend" \
  -H "Authorization: Bearer eyJhbGc..."

PUT /api/v1/organizations/branches/invite/:id/cancel — Cancel Invite

Auth: Protected (Authorization: Bearer <accessToken>) · branch-manager+
Used by: owner-booki-web-app · Role: owner
Description: Cancel a pending branch invite.

Response (200 OK)

{ "message": "Invite cancelled successfully." }

cURL Example

curl -X PUT "http://localhost:4001/api/v1/organizations/branches/invite/507f1f77bcf86cd799439061/cancel" \
  -H "Authorization: Bearer eyJhbGc..."

Notes

  • Invite tokens are valid for 7 days by default.
  • Branch managers created via token have full access to their branch.
  • Branches are soft-deleted if no longer needed.
  • See booki-api/src/validations/branch.validation.ts for exact constraints.