Cost Center

Create, update, and retrieve cost centers and assign users for white label programs

Overview

Cost centers are organizational units used to tag and route spend: for example by department, project, or expense category. Create cost centers before associating them with spend permissions (costCenterIds) or budget mappings (costCenterId).

Typical flow:

  1. Create a cost center: POST /md/api/CostCenters
  2. Update a cost center: PATCH /md/api/CostCenters/{costCenterId}
  3. Retrieve by ID: GET /md/api/CostCenters/{costCenterId}
  4. Assign a user to a cost center: POST /md/api/TeamUserMappings with teamType: "CostCenter"
  5. Update a mapping: PATCH /md/api/TeamUserMappings/{teamUserMappingId}
  6. Remove a user from a cost center: DELETE /md/api/TeamUserMappings/{teamUserMappingId}
  7. Reference the cost center: use the returned id in spend permissions, budget mappings, or expense updates

Authentication: All endpoints require Authorization: Bearer {access_token} and x-appid: {clientId}. The company is resolved from your access token scope: do not send companyId in request bodies. See Authentication.

Code uniqueness: code must be unique within your company (and subsidiary, when subsidiaryId is set). Duplicate codes are rejected on create.

Create Cost Center

POST /md/api/CostCenters

Creates a new cost center for the company associated with your access token. The platform sets companyId, id, active, and status automatically.

Request Body: mandatory fields

Parameter Type Required Description
code string Yes Unique identifier for the cost center (max 100 characters). Often mirrors an ERP or accounting code.
name string Yes Display name for the cost center (max 100 characters).

Optional fields

Parameter Type Default Description
description string - Additional details about the cost center’s purpose.
leaderId string null User ID of the cost center owner or manager.
subsidiaryId string null Subsidiary the cost center belongs to, when your program uses subsidiaries.
externalId string null External system identifier (max 100 characters).
active boolean true Whether the cost center is active.
status string "active" Lifecycle status. Values: active, archived, deleted.

Example Request

Using cURL:

curl -X POST https://sandbox.custodia-tech.com/md/api/CostCenters \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "description": "Marketing department travel expenses",
    "code": "MKT-001",
    "name": "Marketing Travel Expenditure"
  }'

Using JavaScript (fetch):

const response = await fetch('https://sandbox.custodia-tech.com/md/api/CostCenters', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    description: 'Marketing department travel expenses',
    code: 'MKT-001',
    name: 'Marketing Travel Expenditure'
  })
});

const costCenter = await response.json();

Response

Success Response (200 OK)

{
  "description": "Marketing department travel expenses",
  "code": "MKT-001",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Marketing Travel Expenditure",
  "active": true,
  "companyId": "your-company-id",
  "status": "active"
}

Update Cost Center

PATCH /md/api/CostCenters/{costCenterId}

Partially updates an existing cost center. Only include fields you want to change. Do not send companyId or id: they cannot be changed via this endpoint.

Path Parameters

Parameter Type Required Description
costCenterId string Yes UUID of the cost center to update

Request Body

All fields are optional on update. Send only the properties you want to change:

Parameter Type Description
code string Cost center code (max 100 characters). Must remain unique within your company and subsidiary.
name string Display name (max 100 characters).
description string Additional details about the cost center’s purpose.
leaderId string User ID of the cost center owner or manager.
subsidiaryId string Subsidiary the cost center belongs to.
externalId string External system identifier (max 100 characters).
active boolean Whether the cost center is active.
status string Lifecycle status: active, archived, or deleted.

Example Request

Update the display name and description:

Using cURL:

curl -X PATCH https://sandbox.custodia-tech.com/md/api/CostCenters/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing Travel and Events",
    "description": "Travel and event expenses for the marketing department"
  }'

Using JavaScript (fetch):

const costCenterId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';

const response = await fetch(`https://sandbox.custodia-tech.com/md/api/CostCenters/${costCenterId}`, {
  method: 'PATCH',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    name: 'Marketing Travel and Events',
    description: 'Travel and event expenses for the marketing department'
  })
});

const costCenter = await response.json();

Response

Success Response (200 OK)

{
  "description": "Travel and event expenses for the marketing department",
  "code": "MKT-001",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Marketing Travel and Events",
  "active": true,
  "companyId": "your-company-id",
  "status": "active"
}

Get Cost Center by ID

GET /md/api/CostCenters/{costCenterId}

Retrieves a single cost center by its ID. Use the id returned from create cost center.

Path Parameters

Parameter Type Required Description
costCenterId string Yes Unique identifier of the cost center

Example Request

Using cURL:

curl -X GET https://sandbox.custodia-tech.com/md/api/CostCenters/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID"

Using JavaScript (fetch):

const costCenterId = 'a1b2c3d4-e5f6-7890-abcd-ef1234567890';

const response = await fetch(`https://sandbox.custodia-tech.com/md/api/CostCenters/${costCenterId}`, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId
  }
});

const costCenter = await response.json();

Response

Success Response (200 OK)

{
  "description": "Marketing department travel expenses",
  "code": "MKT-001",
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "name": "Marketing Travel Expenditure",
  "active": true,
  "companyId": "your-company-id",
  "leaderId": null,
  "subsidiaryId": null,
  "externalId": null,
  "status": "active",
  "deletedOn": null,
  "deletedBy": null,
  "uiLabel": "MKT-001 Marketing Travel Expenditure"
}

The uiLabel field is a calculated display label combining code and name. It is returned on read but is not accepted on create.

Create Cost Center User Mapping

POST /md/api/TeamUserMappings

Assigns a user to a cost center by creating a cost center user mapping: the join record that links a user (memberId) to a cost center. Users are not added to cost centers by updating the cost center or user record directly.

Prerequisites: the cost center and user must already exist. Create users via Create User and cost centers via create cost center before calling this endpoint.

Same API as org team mapping: Cost center assignments use the shared TeamUserMappings endpoint. Set teamType to CostCenter and pass the cost center UUID in teamId. This is not an org team: do not use an OrgTeam id here.

Request Body: mandatory fields

Parameter Type Required Description
teamId string Yes Cost center UUID to assign the user to. Use the id returned from create cost center: not an org team id.
teamType string Yes Mapping type. Use CostCenter for cost center membership.
memberId string Yes User UUID to add to the cost center.

Optional fields

Parameter Type Default Description
order number 0 Sort order when a user belongs to multiple cost centers.
Unique mapping: Each combination of teamType, teamId, and memberId can exist only once per company. Duplicate mappings are rejected. A user may belong to multiple cost centers: create one mapping per cost center.

Example Request

Using cURL:

curl -X POST https://sandbox.custodia-tech.com/md/api/TeamUserMappings \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "teamId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "teamType": "CostCenter",
    "memberId": "c8d4e2f1-6a3b-4c7d-9e01-2847361950ab"
  }'

Using JavaScript (fetch):

const response = await fetch('https://sandbox.custodia-tech.com/md/api/TeamUserMappings', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    teamId: 'a1b2c3d4-e5f6-7890-abcd-ef1234567890',
    teamType: 'CostCenter',
    memberId: 'c8d4e2f1-6a3b-4c7d-9e01-2847361950ab'
  })
});

const mapping = await response.json();

Response

Success Response (200 OK)

{
  "id": "d9e5f3a2-7b4c-4d8e-a012-3958472610bc",
  "teamId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "teamType": "CostCenter",
  "memberId": "c8d4e2f1-6a3b-4c7d-9e01-2847361950ab",
  "order": 0,
  "companyId": "your-company-id"
}

Save the returned mapping id to update or remove the assignment later.

Update Cost Center User Mapping

PATCH /md/api/TeamUserMappings/{teamUserMappingId}

Partially updates an existing cost center user mapping. Only include fields you want to change. Do not send companyId or id: they cannot be changed via this endpoint.

Path Parameters

Parameter Type Required Description
teamUserMappingId string Yes UUID of the cost center user mapping to update

Request Body

All fields are optional on update. Send only the properties you want to change:

Parameter Type Description
order number Sort order when a user belongs to multiple cost centers.
teamId string Cost center UUID. Must remain unique with teamType and memberId.
teamType string Mapping type. Keep as CostCenter for cost center assignments.
memberId string User UUID. Must remain unique with teamType and teamId.

To move a user to a different cost center, you can update teamId or delete the existing mapping and create a new one.

Example Request

Change the sort order for a user with multiple cost center memberships:

Using cURL:

curl -X PATCH https://sandbox.custodia-tech.com/md/api/TeamUserMappings/d9e5f3a2-7b4c-4d8e-a012-3958472610bc \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "order": 1
  }'

Using JavaScript (fetch):

const teamUserMappingId = 'd9e5f3a2-7b4c-4d8e-a012-3958472610bc';

const response = await fetch(`https://sandbox.custodia-tech.com/md/api/TeamUserMappings/${teamUserMappingId}`, {
  method: 'PATCH',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    order: 1
  })
});

const mapping = await response.json();

Response

Success Response (200 OK)

{
  "id": "d9e5f3a2-7b4c-4d8e-a012-3958472610bc",
  "teamId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "teamType": "CostCenter",
  "memberId": "c8d4e2f1-6a3b-4c7d-9e01-2847361950ab",
  "order": 1,
  "companyId": "your-company-id"
}

Delete Cost Center User Mapping

DELETE /md/api/TeamUserMappings/{teamUserMappingId}

Removes a user from a cost center by deleting the cost center user mapping. Use the mapping id returned from create cost center user mapping. This soft-deletes the mapping record: the user and cost center are not deleted.

Path Parameters

Parameter Type Required Description
teamUserMappingId string Yes UUID of the cost center user mapping to delete

Example Request

Using cURL:

curl -X DELETE https://sandbox.custodia-tech.com/md/api/TeamUserMappings/d9e5f3a2-7b4c-4d8e-a012-3958472610bc \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "x-appid: YOUR_CLIENT_ID"

Using JavaScript (fetch):

const teamUserMappingId = 'd9e5f3a2-7b4c-4d8e-a012-3958472610bc';

const response = await fetch(`https://sandbox.custodia-tech.com/md/api/TeamUserMappings/${teamUserMappingId}`, {
  method: 'DELETE',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'x-appid': clientId
  }
});

const result = await response.json();

Response

Success Response (200 OK)

{
  "count": 1
}

A count of 1 confirms one mapping was removed. A count of 0 means no matching mapping was found (already deleted or invalid ID).

Cost Center Fields

Summary of all fields returned by the API:

Field Type On create Description
code string Required Unique cost center code (max 100 characters).
name string Required Display name (max 100 characters).
description string Optional Free-text description of the cost center.
leaderId string Optional Owner or manager user ID.
subsidiaryId string Optional Subsidiary scope, when applicable.
externalId string Optional Identifier in an external ERP or HR system.
active boolean Optional (default true) Whether the cost center is active.
status string Optional (default active) Lifecycle status: active, archived, or deleted.
id string Set by platform UUID assigned on create.
companyId string Set by platform Company resolved from your access token.
uiLabel string Read-only Calculated label: {code} {name}. Returned on GET only.
deletedOn string (ISO date) Read-only Timestamp when the cost center was deleted, if applicable.
deletedBy string Read-only User ID that deleted the cost center, if applicable.

Error Responses

All endpoints may return the following error responses:

Status Code Description Solution
400 Bad Request Missing required field (code or name), duplicate code, or duplicate cost center user mapping Include mandatory fields, use a unique code, and ensure each user–cost center pair is mapped only once with teamType: "CostCenter"
401 Unauthorized Invalid or missing access token Verify your access token is valid and included in the Authorization header
403 Forbidden Insufficient permissions Verify your access token has the required scopes and permissions
404 Not Found Cost center or cost center user mapping not found Verify the cost center or mapping ID is correct and belongs to your company