Shared Conventions

External integration

This page covers the rules that apply across all Altafid APIs so you do not have to re-learn the same patterns on each domain page.

Audience and scope

This guide covers the full set of Altafid integration APIs, including entity management, saved views, tenant administration, staff management, and data export. All endpoints require standard JWT bearer token authentication and the tenant context headers described below.

Base URL and environment

FieldValueNotes
Base URLhttps://api.altafid.dev.altafid.netUAT endpoint used throughout this documentation.
AuthenticationBearer tokenReturned by /api/auth/login or MFA verification flows.
Tenant contextx-tenant-uuidRequired for all protected domain APIs.

Required headers

After login, most protected APIs expect both the JWT and the tenant/user context headers below.

HeaderRequiredDescription
AuthorizationYesBearer {token} from login or MFA verification.
x-tenant-uuidYesTenant scope for the request.
x-user-emailYesThe authenticated user email from the login response.
x-user-idYesUser UUID from the login response. For tenant staff this is the tenantStaffUuid.
x-user-typeYesTENANT_STAFF, PARTNER_STAFF, or CONTACT.

Pagination conventions

List endpoints use standard page-based pagination.

  • page is zero-based.
  • size defaults to 20 on most endpoints.
  • sort is endpoint-specific for classic GET lists, and an array like ["createdAt,desc"] for v2 filter endpoints.
GET /api/contacts?page=0&size=20
GET /api/organisations/search?searchTerm=alta&page=0&size=20

V2 filtering conventions

Contacts, organisations, and households expose v2 POST-based filtering APIs. The request accepts a list of conditions plus page, size, and sort values.

{
  "filters": [
    { "field": "isActive", "operator": "equals", "value": "true" },
    { "field": "stageName", "operator": "in", "values": ["Prospect", "Client"] }
  ],
  "page": 0,
  "size": 20,
  "sort": ["createdAt,desc"]
}

Distinct values for a filterable field are fetched through the matching /filter-values endpoint:

{
  "field": "stageName",
  "baseFilters": [
    { "field": "isActive", "operator": "equals", "value": "true" }
  ],
  "page": 0,
  "size": 20
}

Error handling

The API returns standard HTTP status codes. Client code should check the status first, then parse the response body if present.

StatusTypical meaningRecommended action
400Validation or malformed inputFix the payload, path variable, or query parameter.
401Missing or invalid authenticationRe-authenticate or refresh the token.
403Authenticated but not allowedCheck role, tenant context, and ownership rules.
404Resource not foundVerify UUIDs and whether the resource belongs to the current tenant.
409State conflictUsed on duplicate resources or invalid state transitions.
Important: some endpoints return only the HTTP status with an empty body on failure, while others return a structured error payload. Do not assume a uniform error schema across all endpoints.

Error response formats

When an error body is present, it follows one of two schemas depending on which part of the platform handles the error.

Standard error response — returned by most endpoints. Includes a machine-readable errorCode with the format BE#### that your code can switch on:

{
  "errorCode": "BE0101",
  "message": "Contact not found",
  "status": 404,
  "path": "/api/contacts/UNKNOWN-UUID",
  "timestamp": "2024-01-15T10:30:00",
  "details": null
}

For validation errors (400), the details array contains field-level messages:

{
  "errorCode": "BE0201",
  "message": "Validation failed",
  "status": 400,
  "path": "/api/contacts",
  "timestamp": "2024-01-15T10:30:00",
  "details": [
    "firstName: must not be blank",
    "contactType: must not be null"
  ]
}

Legacy error response — returned by some older endpoints. Uses a details map instead of an array:

{
  "timestamp": "2024-01-15T10:30:00.000Z",
  "status": 400,
  "error": "Bad Request",
  "message": "Validation failed",
  "details": {
    "firstName": "must not be blank"
  }
}

Dynamic configuration lookups

Some fields on contacts and organisations accept values that are configured per-tenant rather than hardcoded in the platform. Retrieve the valid options for these fields at runtime using the endpoints below.

FieldEntityEndpointDescription
stage Contact GET /api/core/platformconfigs/v1/contacts/stages Pipeline stages configured for the current tenant.
contactSource Contact GET /api/core/platformconfigs/v1/contacts/sources Lead source options (e.g. Referral, Event, Website).
segment Contact GET /api/core/platformconfigs/v1/contacts/segments Market segment classifications (e.g. Retail, Institutional).
industry Organisation GET /api/industries Industry options with display names for UI rendering.
country fields Contact / Org GET /api/core/geo/v1/countries ISO country list for address and citizenship fields.
cities Contact / Org GET /api/core/geo/v1/cities?country={code} City options for a given country code.
phoneCountryCode Contact / Org GET /api/core/geo/v1/phone-codes Phone dialling code options by country.

Example: fetch pipeline stages

curl "https://api.altafid.dev.altafid.net/api/core/platformconfigs/v1/contacts/stages" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "x-tenant-uuid: YOUR_TENANT_UUID" \
  -H "x-user-email: YOUR_EMAIL" \
  -H "x-user-id: YOUR_USER_ID" \
  -H "x-user-type: TENANT_STAFF"

The response is a list of stage objects with a code field that you pass as the stageName value when creating or updating a contact. Because stages are tenant-defined, always fetch them from the API rather than hardcoding them in your integration.

Sample responses

Pipeline stages, contact sources, and contact segments — all three endpoints return the same structure:

[
  {
    "code": "prospect",
    "displayName": "Prospect",
    "enabled": true,
    "deleted": false,
    "sortOrder": 1,
    "createdAt": "2024-01-10T08:00:00Z",
    "updatedAt": "2024-01-10T08:00:00Z"
  },
  {
    "code": "client",
    "displayName": "Client",
    "enabled": true,
    "deleted": false,
    "sortOrder": 2,
    "createdAt": "2024-01-10T08:00:00Z",
    "updatedAt": "2024-01-10T08:00:00Z"
  }
]

Use the code value when setting stageName, contactSource, or segmentName on a contact. The displayName is intended for rendering in UIs. Only enabled: true and deleted: false items are valid for new records.

IndustriesGET /api/industries returns a flat list of name/displayName pairs:

[
  { "name": "TECHNOLOGY", "displayName": "Technology" },
  { "name": "FINANCIAL_SERVICES", "displayName": "Financial Services" },
  { "name": "HEALTHCARE", "displayName": "Healthcare" }
]

Use the name value when setting the industry field on an organisation.

CountriesGET /api/core/geo/v1/countries returns an array of country objects. Use the optional fields query parameter to limit which fields are returned:

GET /api/core/geo/v1/countries?fields=cca3,name.common

[
  { "cca3": "CHL", "name": { "common": "Chile" } },
  { "cca3": "ARG", "name": { "common": "Argentina" } },
  { "cca3": "USA", "name": { "common": "United States" } }
]

Use the cca3 ISO-3 code for address fields such as identityCountry, countryOfBirth, and countryOfCitizenship.

Sample data guidance

  • Reuse a single documented tenant and user where possible.
  • Prefer examples that can be re-run safely — list, search, and filter requests.
  • For create and update samples, use obviously illustrative values. UUIDs returned from your tenant will differ.
  • For note attachments, treat upload URLs as short-lived and environment-specific.