Companies
Create a company tenant for white label programs
Overview
A company is the top-level tenant in Custodia. Every user, card, budget, and activity belongs to a company. Create the company first, then use the returned id as companyId in other APIs (for example Create user, Spend templates, or Chart of accounts).
Typical onboarding flow:
- Create a company:
POST /md/api/Companies - Create admin users:
POST /md/api/User - Configure program settings: spend templates, budgets, card products, and so on
Authentication: Requires Authorization: Bearer {access_token} and x-appid: {clientId}. Company create requires a program-level credential with permission to provision tenants (for example card-issuer-admin). See Authentication.
name must be unique across the platform. The platform sets id, status (initially new), license, and card-issuer keywords automatically from your program context: do not send id or status on create.
Create Company
Creates a new company tenant. Save the returned id: it is the companyId used across the rest of the partner APIs.
Request Body: mandatory fields
| Parameter | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Company or organization display name (max 100 characters). Must be globally unique. |
Recommended fields for onboarding
Only name is required by the API, but card programs and user provisioning typically need the fields below at create time or shortly after.
| Parameter | Type | Description |
|---|---|---|
dns |
string | Corporate email domain(s). Semicolon-delimited format: ;acme.com;subsidiary.com; |
billingAddress |
Address | Primary business address. See Address fields. |
legal |
LegalInfo | Legal entity details for KYC and compliance. See Legal fields. |
legalAddr |
Address | Legal address when different from billingAddress. |
externalId |
string | Your external reference ID for the company (max 64 characters). |
website |
string | Company website URL. |
Address fields
Used in billingAddress and legalAddr:
| Field | Type | Description |
|---|---|---|
houseNumber | string | Street number. |
street | string | Street name. |
city | string | City. |
county | string | County or municipality. |
state | string | State or province code. |
country | string | ISO country code (for example US). |
postalCode | string | Postal or ZIP code. |
phone | string | Business phone number. |
Legal fields
Used in the nested legal object:
| Field | Type | Description |
|---|---|---|
taxId | string | Tax identification number. |
legalName | string | Registered legal entity name. |
structure | string | One of LLC, CORPORATION, SOLE_PROPRIETORSHIP, PARTNERSHIP, COOPERATIVE, OTHER. |
established | string | Date established (yyyy-MM-dd). |
country | string | Country of incorporation (ISO code). |
stateOfIncorporation | string | State of incorporation (required for US entities). |
industry | string | Industry classification. |
isPublic | boolean | Whether the company is publicly traded (default false). |
symbol | string | Stock ticker symbol (when isPublic is true). |
Example Request
Using cURL:
curl -X POST https://sandbox.custodia-tech.com/md/api/Companies \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-H "x-appid: YOUR_CLIENT_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Acme Field Services",
"externalId": "ERP-ACME-001",
"website": "https://www.acme.example",
"dns": ";acme.example;",
"billingAddress": {
"houseNumber": "100",
"street": "Market Street",
"city": "San Francisco",
"state": "CA",
"country": "US",
"postalCode": "94105",
"phone": "+1-415-555-0100"
},
"legal": {
"taxId": "12-3456789",
"legalName": "Acme Field Services Inc.",
"structure": "CORPORATION",
"established": "2018-03-15",
"country": "US",
"stateOfIncorporation": "DE",
"industry": "Field Services",
"isPublic": false
},
"legalAddr": {
"houseNumber": "100",
"street": "Market Street",
"city": "San Francisco",
"state": "CA",
"country": "US",
"postalCode": "94105"
}
}'
Using JavaScript (fetch):
const response = await fetch('https://sandbox.custodia-tech.com/md/api/Companies', {
method: 'POST',
headers: {
'Authorization': `Bearer ${accessToken}`,
'x-appid': clientId,
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'Acme Field Services',
externalId: 'ERP-ACME-001',
dns: ';acme.example;',
billingAddress: {
houseNumber: '100',
street: 'Market Street',
city: 'San Francisco',
state: 'CA',
country: 'US',
postalCode: '94105',
phone: '+1-415-555-0100'
},
legal: {
taxId: '12-3456789',
legalName: 'Acme Field Services Inc.',
structure: 'CORPORATION',
established: '2018-03-15',
country: 'US',
stateOfIncorporation: 'DE',
isPublic: false
}
})
});
const company = await response.json();
Response
Success Response (200 OK)
{
"id": "7332ad13-d460-457d-b73f-0e1681f060fc",
"name": "Acme Field Services",
"status": "new",
"externalId": "ERP-ACME-001",
"website": "https://www.acme.example",
"dns": ";acme.example;",
"license": "enterprise",
"maxUsers": 50,
"maxCards": 50,
"maxAdmins": 5,
"tenantType": "normal",
"createdOn": "2026-07-08T02:10:00.000Z"
}
The company starts in new status. Use the returned id as companyId when creating users and configuring the program. Lifecycle status changes (for example to active) are handled by Custodia operations: do not set status directly via partner APIs.
Company Fields (summary)
| Parameter | Type | On create | Description |
|---|---|---|---|
id |
string | Set by platform | Company UUID. Use as companyId in other APIs. |
name |
string | Required | Display name (globally unique). |
status |
string | Set by platform | Lifecycle status. New companies start as new. |
license |
string | Set by platform | License tier (for example enterprise). |
partnerId |
string | Set by platform | Partner association from your access token. |
dns |
string | Optional | Corporate email domains. |
externalId |
string | Optional | External reference ID. |
Error Responses
| Status Code | Description | Solution |
|---|---|---|
400 Bad Request |
Missing name or invalid nested object (address, legal) |
Send name and verify address and legal field formats |
401 Unauthorized |
Invalid, missing, or expired access token | Re-authenticate via POST /md/api/Application/authenticate |
403 Forbidden |
Insufficient permissions to create companies | Ensure your program credential has company provisioning access |
422 Unprocessable Entity |
Validation failed: for example duplicate name or invalid legal.structure |
Use a unique company name and valid enum values for legal structure |
Related documentation
- Create user: requires
companyIdfrom this endpoint - Spend templates
- Chart of accounts
- Glossary: companyId
- Authentication