The Base Public API lets you integrate your CRM, advocacy programs and content workflows with the Base platform. All endpoints in this document are part of the stable v1 contract.
All requests require a bearer token in the Authorization header:
Authorization: Bearer <your_jwt_token>
Tokens are issued from your company's admin console under Settings → API tokens.
Ask your account administrator if you do not have one. Tokens carry the set of
authorities (api.user.list, api.points.add, etc.) granted to the issuing user —
if a request returns 403, the token is missing the authority the endpoint requires.
https://stage.customershome.com/acauth
for staging, https://prod.customershome.com/acauth for production.2026-05-12T08:30:00Z).550e8400-e29b-41d4-a716-446655440000).page (0-indexed), size,
and sort. Maximum size is 500 unless the endpoint says otherwise./api/v1 is the current stable contract.
Breaking changes ship as /api/v2 rather than mutating /api/v1 in place; v1
endpoints are supported for at least 12 months after a v2 successor lands.v1 endpoints are not currently rate-limited at the API edge, but please call considerately:
*/bulk, /users-by-dates, */batch) over loops on
the single-item variant.sinceLastModified for incremental sync rather than re-fetching the full
dataset on every poll.5xx responses and respect Retry-After if present
on a future 429 response.Sustained traffic above ~10 requests/second per token may be subject to throttling in a future release. Subscribe to release notes for the announcement.
GET / DELETE / PUT operations are idempotent by definition — replaying the
same request never produces a different result.POST create endpoints do not currently support an Idempotency-Key header.
Retries after a network failure may create duplicate records; design retries
around your own deduplication key (e.g. external CRM contact id).The API uses standard HTTP status codes. Non-2xx responses carry a JSON body with the shape:
{ "title": "Bad Request", "status": 400, "detail": "Page size must be less than 500" }
Common codes:
| Status | Meaning |
|---|---|
200 |
Success with a JSON body |
201 |
Created — typically returned by POST endpoints with the new resource's UUID |
204 |
Success with no body — typically returned by DELETE and idempotent operations |
400 |
The request body or parameters failed validation |
401 |
Missing or invalid bearer token |
403 |
The token does not carry the required authority for this endpoint |
404 |
The target resource does not exist |
409 |
Conflict (most often a duplicate name on create/update) |
500 |
Internal error — safe to retry with exponential backoff |
CRM → Base sync. Use Import contacts by email (or by-contact-id) to push
advocates in bulk, then Modify advocate custom attributes (bulk variant) to push
custom-field values. For accounts and opportunities, the Update account data and
Upsert opportunity attributes endpoints perform create-or-update in one call.
Activity tracking. Call Trigger activity whenever an advocate completes a
tracked event (closed a deal, posted a review, attended a webinar). The activity
type configuration in admin determines points awarded and ASK progression.
Leaderboard widget. Call Get leaderboard for the global ranking; call
Get leaderboard entry by email to render the current advocate's row inline.
Both are cheap to call on page load.
Discovery before write. List endpoints (List custom attributes,
List custom object mappings, List activity types) tell you the valid keys
and types for the corresponding write endpoints. Cache the result client-side —
schemas change rarely.
For historical reasons, some resource names in the API differ from their UI labels. See the per-endpoint descriptions for context; the most important mappings are:
challenge in the API = ASK in the UIevidence in the API = content in the UIcontact (in entity parameters) = advocate recordUpdate existing custom object records on advocates. Each batch item identifies the record by its instance ID (returned from a prior create) and supplies the attribute values to change. Items are processed independently — inspect per-record results in the response.
Use this for incremental sync of fields that change over time (e.g. subscription tier, renewal date).
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/advocate/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"users": [
{
"advocateEmail": "ada@example.com",
"objects": [
{
"objectName": "subscription",
"recordId": "sub-2026-001",
"attributes": [
{ "attributeName": "plan", "values": ["Enterprise Plus"] }
]
}
]
}
]
}'
required | Array of objects (AdvocateAttributesAndRecordsDTO) non-empty |
{- "users": [
- {
- "advocateUuid": "string",
- "advocateEmail": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
], - "objects": [
- {
- "objectName": "string",
- "recordId": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
]
}
]
}
]
}Create one or more custom object records (and their attribute values) on advocates. Each item in
the batch identifies a target advocate (by UUID or email) and a custom object apiName, then
provides the attribute values to set.
Items are processed independently; per-record results — success UUID or error context — are returned in the response body. Use this for bulk-loading multi-row data like subscription history or meeting notes from your CRM.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/advocate/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"users": [
{
"advocateEmail": "ada@example.com",
"objects": [
{
"objectName": "subscription",
"recordId": "sub-2026-001",
"attributes": [
{ "attributeName": "plan", "values": ["Enterprise"] },
{ "attributeName": "started_at", "values": ["2026-01-01"] }
]
}
]
}
]
}'
required | Array of objects (AdvocateAttributesAndRecordsDTO) non-empty |
{- "users": [
- {
- "advocateUuid": "string",
- "advocateEmail": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
], - "objects": [
- {
- "objectName": "string",
- "recordId": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
]
}
]
}
]
}Delete custom object records on advocates. Each batch item identifies the target advocate
(advocateUuid or advocateEmail), the custom object (objectName), and a list of record ids
(recordIds) to delete. Passing an empty recordIds array deletes every record of that object
type on the advocate. Items are processed independently — per-record outcomes are returned.
Irreversible — the deleted records cannot be recovered.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/advocate/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"users": [
{
"advocateEmail": "ada@example.com",
"objectName": "subscription",
"recordIds": ["sub-2026-001"]
}
]
}'
required | Array of objects (DeleteAdvocateRecordsDTO) non-empty |
{- "users": [
- {
- "advocateUuid": "string",
- "advocateEmail": "string",
- "objectName": "string",
- "recordIds": [
- "string"
]
}
]
}Update existing custom object records on accounts. Each batch item identifies the record by its instance ID (returned from a prior create) and supplies the attribute values to change. Items are processed independently — inspect per-record results in the response.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/account/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"accounts": [
{
"accountName": "Analytical Engines Inc.",
"objects": [
{
"objectName": "primary_contact",
"recordId": "ext-pc-001",
"attributes": [
{ "attributeName": "email", "values": ["ada.lovelace@example.com"] }
]
}
]
}
]
}'
required | Array of objects (AccountAttributesAndRecordsDTO) non-empty |
{- "accounts": [
- {
- "accountUuid": "string",
- "accountName": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
], - "objects": [
- {
- "objectName": "string",
- "recordId": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
]
}
]
}
]
}Create one or more custom object records (and their attribute values) on accounts. Each batch
item identifies a target account (by UUID or name) and a custom object apiName, then provides
the attribute values to set.
Items are processed independently — inspect per-record results in the response body.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/account/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"accounts": [
{
"accountName": "Analytical Engines Inc.",
"objects": [
{
"objectName": "primary_contact",
"recordId": "ext-pc-001",
"attributes": [
{ "attributeName": "full_name", "values": ["Ada Lovelace"] },
{ "attributeName": "email", "values": ["ada@example.com"] }
]
}
]
}
]
}'
required | Array of objects (AccountAttributesAndRecordsDTO) non-empty |
{- "accounts": [
- {
- "accountUuid": "string",
- "accountName": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
], - "objects": [
- {
- "objectName": "string",
- "recordId": "string",
- "attributes": [
- {
- "attributeName": "string",
- "values": [
- "string"
]
}
]
}
]
}
]
}Delete custom object records on accounts. Each batch item identifies the target account
(accountUuid or accountName), the custom object (objectName), and a list of record ids
(recordIds) to delete. Passing an empty recordIds array deletes every record of that object
type on the account. Items are processed independently — per-record outcomes are returned.
Irreversible — the deleted records cannot be recovered.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/account/custom-object-record/batch' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"accounts": [
{
"accountName": "Analytical Engines Inc.",
"objectName": "primary_contact",
"recordIds": ["ext-pc-001"]
}
]
}'
required | Array of objects (DeleteAccountRecordsDTO) non-empty |
{- "accounts": [
- {
- "accountUuid": "string",
- "accountName": "string",
- "objectName": "string",
- "recordIds": [
- "string"
]
}
]
}Read custom object records and their attribute values for one account. Identify the account by
UUID or name (one of the two is required); identify the custom object by objectName (its
apiName from the mapping).
Without instanceId, returns every record of that object type attached to the account.
With instanceId, narrows the response to a single record. A common flow is: call the listing
endpoint to discover instance IDs, then call this endpoint with one to read a specific record's
attributes.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/account/custom-object-record/primary_contact?accountName=Analytical%20Engines%20Inc.' \
-H 'Authorization: Bearer <jwt_token>'
| objectName required | string API name of the custom object |
| accountUuid | string UUID of the target account (either accountUuid or accountName is required) |
| accountName | string Name of the target account (either accountUuid or accountName is required) |
| instanceId | string Optional instance ID to narrow to a specific custom object record |
Define and manage custom data attributes on platform entities. Allowed entity values: contact (advocate record), account, opportunity, nomination.
Update a custom attribute. Both PUT and PATCH on this endpoint accept the same
PatchCustomDataAttributeApiDTO body, and in both cases fields omitted (or sent as null) are
left unchanged (booleans are boxed, so null does NOT mean false).
The two verbs differ only in the authority they require: PUT needs api.custom_attribute.add
(the same scope used for Create), PATCH needs api.custom_attribute.update. New integrations
should prefer PATCH so the token scope is narrow.
The attribute name, type, and owning entity cannot be changed once created — recreate the
attribute under a new name if a different type is required.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/custom-attributes/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"label": "Favorite color",
"description": "Updated description",
"values": ["red", "green", "blue", "yellow"],
"editableByAdvocate": true,
"mandatory": false
}'
| uuid required | string UUID of the attribute to update |
| label | string New human-readable label |
| description | string New description |
| values | Array of strings unique New list of allowed values for picklist-style attributes |
| editableByAdvocate | boolean Whether the advocate can edit this attribute themselves |
| mandatory | boolean Whether a value for this attribute is required |
| onActivation | boolean Show in activation flow |
| showInSourcing | boolean Show in sourcing flows |
| showInReport | boolean Show in admin reports |
| multipleValues | boolean Whether the attribute can hold multiple values |
| showInJoinReferencePoolChallenge | boolean Show in the Join Reference Pool ASK form |
| showInReferenceRequestDialog | boolean Show in the reference request dialog |
| showInMarketingRequestDialog | boolean Show in the marketing request dialog |
| requiredInNominationDialog | boolean Required when nominating an advocate |
{- "label": "Favorite color",
- "description": "Updated description",
- "values": [
- "red",
- "green",
- "blue",
- "yellow"
], - "editableByAdvocate": true,
- "mandatory": true,
- "onActivation": true,
- "showInSourcing": true,
- "showInReport": true,
- "multipleValues": true,
- "showInJoinReferencePoolChallenge": true,
- "showInReferenceRequestDialog": true,
- "showInMarketingRequestDialog": true,
- "requiredInNominationDialog": true
}Delete a custom attribute by UUID. The attribute is removed from every record that had a value for it; existing record values for this attribute are also deleted and cannot be recovered.
Returns 204 No Content on success. Use with care — there is no soft-delete.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/custom-attributes/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer <jwt_token>'
| uuid required | string UUID of the attribute to delete |
Partially update a custom attribute. Only fields present in the request are changed; omitted
fields keep their current value (boolean toggles use Boolean so null means "leave unchanged",
not "set to false").
Use this endpoint for everyday tweaks (label change, adding allowed picklist values, toggling
visibility flags). The attribute name, type, and owning entity remain immutable.
Example:
curl -X PATCH 'https://prod.customershome.com/acauth/api/v1/custom-attributes/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{ "label": "Favourite colour" }'
| uuid required | string UUID of the attribute to patch |
| label | string New human-readable label |
| description | string New description |
| values | Array of strings unique New list of allowed values for picklist-style attributes |
| editableByAdvocate | boolean Whether the advocate can edit this attribute themselves |
| mandatory | boolean Whether a value for this attribute is required |
| onActivation | boolean Show in activation flow |
| showInSourcing | boolean Show in sourcing flows |
| showInReport | boolean Show in admin reports |
| multipleValues | boolean Whether the attribute can hold multiple values |
| showInJoinReferencePoolChallenge | boolean Show in the Join Reference Pool ASK form |
| showInReferenceRequestDialog | boolean Show in the reference request dialog |
| showInMarketingRequestDialog | boolean Show in the marketing request dialog |
| requiredInNominationDialog | boolean Required when nominating an advocate |
{- "label": "Favorite color",
- "description": "Updated description",
- "values": [
- "red",
- "green",
- "blue",
- "yellow"
], - "editableByAdvocate": true,
- "mandatory": true,
- "onActivation": true,
- "showInSourcing": true,
- "showInReport": true,
- "multipleValues": true,
- "showInJoinReferencePoolChallenge": true,
- "showInReferenceRequestDialog": true,
- "showInMarketingRequestDialog": true,
- "requiredInNominationDialog": true
}List custom attributes defined for a given entity (contact = advocate, account, opportunity, nomination).
By default the response includes attributes inherited from a connected CRM in addition to Base-native
attributes; pass includeCRM=false to see only the attributes you defined in Base. Use this to
discover the schema before reading or writing attribute values on a specific record.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/custom-attributes?entity=contact&includeCRM=true' \
-H 'Authorization: Bearer <jwt_token>'
| entity required | string Entity name whose attributes to list. Accepted values: |
| includeCRM | boolean Default: true Include attributes inherited from a connected CRM (default true) |
Define a new custom attribute on an entity. The name becomes the API key used in all subsequent
reads and writes — it must be unique per entity, all-lowercase, and only contain letters / digits /
underscores. label is what admins and advocates see in the UI; you can change it later via PATCH.
For picklist attributes set type: "Enumerated" and supply the allowed values up front. To allow
selecting multiple values from that list, also set multipleValues: true. For booleans use
type: "Boolean" and leave values empty.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/custom-attributes' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "favorite_color",
"label": "Favorite color",
"description": "Advocate favorite color",
"type": "Enumerated",
"entity": "contact",
"values": ["red", "green", "blue"],
"editableByAdvocate": true
}'
| name required | string [ 1 .. 64 ] characters ^(?!.*\s)[a-z0-9_]+$ Internal API name. 1 to 64 characters, lowercase letters/digits/underscores only. |
| label required | string Human-readable label shown in UI |
| description | string Optional description |
| type required | string Enum: "String" "Integer" "Float" "Boolean" "Date" "Enumerated" Attribute type |
| entity required | string Entity to attach this attribute to. Accepted values: |
| values | Array of strings unique Allowed values for picklist-style attribute types |
| editableByAdvocate | boolean Whether the advocate can edit this attribute themselves |
| mandatory | boolean Whether a value for this attribute is required |
| onActivation | boolean Show in activation flow |
| showInSourcing | boolean Show in sourcing flows |
| showInReport | boolean Show in admin reports |
| multipleValues | boolean Whether the attribute can hold multiple values |
| showInJoinReferencePoolChallenge | boolean Show in the Join Reference Pool ASK form |
| showInReferenceRequestDialog | boolean Show in the reference request dialog |
| showInMarketingRequestDialog | boolean Show in the marketing request dialog |
| requiredInNominationDialog | boolean Required when nominating an advocate |
{- "name": "favorite_color",
- "label": "Favorite color",
- "description": "Advocate's favorite color",
- "type": "String",
- "entity": "contact",
- "values": [
- "red",
- "green",
- "blue"
], - "editableByAdvocate": false,
- "mandatory": false,
- "onActivation": false,
- "showInSourcing": false,
- "showInReport": false,
- "multipleValues": false,
- "showInJoinReferencePoolChallenge": false,
- "showInReferenceRequestDialog": false,
- "showInMarketingRequestDialog": false,
- "requiredInNominationDialog": false
}Retrieve nomination records that match the provided filter. Nominations are advocate-marketing requests created by salespeople or marketing — typically asking an advocate to participate in a case study, reference call, review, etc.
The filter requires a date range (dateFrom/dateTo) and accepts optional statuses, marketing
admin UUIDs, salesperson names, specific nomination UUIDs, activity type names, and a free-text
search. Set includeRepeatedNominations=true to surface advocates who were nominated more than
once in the window. Use this for reporting / analytics dashboards.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/nomination' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"dateFrom": "2026-01-01",
"dateTo": "2026-03-31",
"statuses": ["IN_PROGRESS", "APPROVED"],
"includeRepeatedNominations": false
}'
| dateFrom required | string <date> Earliest creation date to include (ISO 8601 date) |
| dateTo required | string <date> Latest creation date to include (ISO 8601 date) |
| statuses | Array of strings Items Enum: "INITIAL" "IN_PROGRESS" "REJECTED" "APPROVED" "COMPLETED" Optional list of nomination statuses to filter by |
| marketingAdminUuids | Array of strings Optional list of marketing admin UUIDs to filter by |
| nominationUuids | Array of strings Optional list of specific nomination UUIDs to return |
| salespersonNames | Array of strings Optional list of salesperson names to filter by |
| activityTypeNames | Array of strings Optional list of activity type names to filter by |
| searchQuery | string Optional free-text search query across nomination fields |
| includeRepeatedNominations | boolean Include nominations that have been requested for the same advocate multiple times |
{- "dateFrom": "2026-01-01",
- "dateTo": "2026-03-31",
- "statuses": [
- "INITIAL"
], - "marketingAdminUuids": [
- "string"
], - "nominationUuids": [
- "string"
], - "salespersonNames": [
- "string"
], - "activityTypeNames": [
- "string"
], - "searchQuery": "renewal",
- "includeRepeatedNominations": false
}Update an existing content category. Only present fields are changed — omit a field to leave it untouched.
Setting tagUuids replaces the full set of tags in this category (it is not an add-list).
Tags removed from the set lose their category but are not deleted.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/content-categories/660e8400-e29b-41d4-a716-446655440111' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"description": "Updated description for technology",
"tagUuids": ["550e8400-e29b-41d4-a716-446655440000"]
}'
| uuid required | string UUID of the category to update |
| uuid | string UUID of the category to update |
| name | string [ 1 .. 255 ] characters Optional new category name (1 to 255 characters) |
| description | string Optional new description |
| tagUuids | Array of strings[ items non-empty ] Optional new list of tag UUIDs to include in this category |
{- "uuid": "660e8400-e29b-41d4-a716-446655440111",
- "name": "Updated Technology",
- "description": "Updated description for technology",
- "tagUuids": [
- "tag-uuid-1",
- "tag-uuid-4"
]
}Delete an existing content category. Tags previously in this category are not deleted; they become uncategorized (you can re-assign them to another category via Update Content Tag).
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/content-categories/660e8400-e29b-41d4-a716-446655440111' \
-H 'Authorization: Bearer <jwt_token>'
| uuid required | string UUID of the category to delete |
Update multiple content categories in a single request. The body is a map keyed by category UUID,
so each entry follows the same semantics as the single-update endpoint (notably: tagUuids is a
full replace, not a merge). Up to 100 entries per request.
Each entry is processed independently — inspect successful and failed in the response.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/content-categories/bulk' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"660e8400-e29b-41d4-a716-446655440111": {
"description": "Updated tech description"
},
"660e8400-e29b-41d4-a716-446655440222": {
"tagUuids": ["tag-uuid-5", "tag-uuid-6"]
}
}'
additional property | object (UpdateContentTagCategory) Payload for updating an existing content category. Only present fields are changed. |
{- "property1": {
- "uuid": "660e8400-e29b-41d4-a716-446655440111",
- "name": "Updated Technology",
- "description": "Updated description for technology",
- "tagUuids": [
- "tag-uuid-1",
- "tag-uuid-4"
]
}, - "property2": {
- "uuid": "660e8400-e29b-41d4-a716-446655440111",
- "name": "Updated Technology",
- "description": "Updated description for technology",
- "tagUuids": [
- "tag-uuid-1",
- "tag-uuid-4"
]
}
}Create multiple content categories in a single request. Accepts 1 to 100 items; each item is
processed independently. The response separates successful and failed items so a partial
success is still a 201 — inspect the body.
Useful when migrating a content taxonomy from another system in one shot rather than looping on the single-create endpoint.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/content-categories/bulk' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '[
{ "name": "Technology", "description": "Tech content", "tagUuids": ["tag-uuid-1"] },
{ "name": "Marketing", "description": "Marketing content", "tagUuids": ["tag-uuid-2"] }
]'
| name required | string [ 1 .. 255 ] characters Category display name. Required; 1 to 255 characters. |
| description | string Optional human-readable description of the category |
| tagUuids required | Array of strings Tag UUIDs to include in this category. At least one is required. |
[- {
- "name": "Technology",
- "description": "All technology-related content",
- "tagUuids": [
- "tag-uuid-1",
- "tag-uuid-2"
]
}
]Retrieve a paginated list of content categories with optional substring name filtering. Use the
returned uuid of each category to scope a subsequent List Content Tags call to that category.
Maximum page size is 500; requests above that limit return 400.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/content-categories?name=tech&page=0&size=20' \
-H 'Authorization: Bearer <jwt_token>'
| name | string Filter categories by name (substring match) |
required | object (Pageable) |
Create a new content category and assign one or more existing tags to it. name must be unique
within the company; tagUuids is required and must contain at least one tag.
If you need to create the tags first, call Create Content Tag (or its bulk variant) before this endpoint.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/content-categories' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "Technology",
"description": "All technology-related content",
"tagUuids": ["550e8400-e29b-41d4-a716-446655440000", "550e8400-e29b-41d4-a716-446655440001"]
}'
| name required | string [ 1 .. 255 ] characters Category display name. Required; 1 to 255 characters. |
| description | string Optional human-readable description of the category |
| tagUuids required | Array of strings Tag UUIDs to include in this category. At least one is required. |
{- "name": "Technology",
- "description": "All technology-related content",
- "tagUuids": [
- "tag-uuid-1",
- "tag-uuid-2"
]
}Update the description and/or category of an existing content tag. The tag name is immutable
via this endpoint; create a new tag and delete the old one if you need to rename.
Pass tagCategoryUuid: null to move the tag back to top-level.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/content-tags/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"description": "Updated description",
"tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440222"
}'
| uuid required | string UUID of the tag to update |
| description | string Optional new description of the tag |
| tagCategoryUuid | string Optional new parent content category UUID |
{- "description": "Updated description",
- "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}Delete an existing content tag. The tag is removed from every content item that referenced it; the content items themselves are not deleted. Deleting a tag that does not exist returns 404 — handle the not-found case explicitly if your sync runs may already have removed the tag.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/content-tags/550e8400-e29b-41d4-a716-446655440000' \
-H 'Authorization: Bearer <jwt_token>'
| uuid required | string UUID of the tag to delete |
Update multiple content tags in a single request. The body is a map keyed by tag UUID, so the same
description / tagCategoryUuid semantics as the single-update endpoint apply per entry. Up to 100
entries per request.
Each entry is processed independently — inspect successful and failed in the response to find
out which entries committed. Useful for re-categorizing tags in bulk, e.g. moving all tags from a
deprecated category to a new one.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/content-tags/bulk' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"550e8400-e29b-41d4-a716-446655440000": {
"tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440222"
},
"550e8400-e29b-41d4-a716-446655440001": {
"description": "Updated description"
}
}'
additional property | object (UpdateContentTag) Payload for updating an existing content tag. Only present fields are changed. |
{- "property1": {
- "description": "Updated description",
- "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}, - "property2": {
- "description": "Updated description",
- "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}
}Create multiple content tags in a single request. Accepts 1 to 100 items; each item is processed
independently. The response contains a successful array of newly created UUIDs and a failed
array with per-item error context (most commonly a DUPLICATE_NAME error when the tag already exists).
A partial failure (some items in failed) is still a 200 response — inspect the body to find out
which items were created. Use this endpoint when seeding a new company or importing tags from a
CRM rather than calling the single-create endpoint in a loop.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/content-tags/bulk' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '[
{ "name": "Product Launch", "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111" },
{ "name": "Customer Success" }
]'
| name required | string [ 1 .. 255 ] characters Tag display name. Required; 1 to 255 characters. |
| description | string Optional human-readable description of the tag |
| tagCategoryUuid | string Optional UUID of the parent content category |
[- {
- "name": "Product Launch",
- "description": "Used to mark content related to product launch campaigns",
- "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}
]Retrieve a paginated list of content tags with optional filtering by name (substring match) and category UUID.
Typical flow: list categories first to obtain contentCategoryUuid, then list tags scoped to that category.
Maximum page size is 500; requests above that limit return 400.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/content-tags?contentCategoryUuid=660e8400-e29b-41d4-a716-446655440111&page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
| name | string Filter tags by name (substring match) |
| contentCategoryUuid | string Filter tags by content category UUID |
required | object (Pageable) |
Create a new content tag.
name is required and must be unique within the company (case-insensitive). Pass a tagCategoryUuid
to put the new tag under an existing category, or leave it null to create a top-level tag. The response
body returns the new UUID; use it as the identifier for subsequent update or delete calls.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/content-tags' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "Product Launch",
"description": "Used to mark content related to product launch campaigns",
"tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}'
| name required | string [ 1 .. 255 ] characters Tag display name. Required; 1 to 255 characters. |
| description | string Optional human-readable description of the tag |
| tagCategoryUuid | string Optional UUID of the parent content category |
{- "name": "Product Launch",
- "description": "Used to mark content related to product launch campaigns",
- "tagCategoryUuid": "660e8400-e29b-41d4-a716-446655440111"
}Core customer-facing V1 endpoints: users, advocates, accounts, opportunities, activities, leaderboard, points, imports, and registration confirmation.
Get full data for a single user by external auth id (the identifier issued by the SSO provider — not the email and not the advocate UUID). Returns 404 if the user does not exist in the caller's company.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/users/auth0|abcd1234' \
-H 'Authorization: Bearer <jwt_token>'
| id required | string External auth id of the user |
Update custom attribute values for an existing user identified by external SSO auth id. The
payload mirrors Modify custom attributes for a single advocate — three optional maps for
addCustomAttributes, updateCustomAttributes, and removeCustomAttributes. The endpoint does
not change profile fields (name, email, jobTitle, company) directly; profile fields are managed
via the registration / SSO flow.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/users/auth0|abcd1234' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"updateCustomAttributes": { "favorite_color": ["green"] },
"removeCustomAttributes": ["deprecated_flag"]
}'
| id required | string External auth id of the user |
object | |
object | |
| removeCustomAttributes | Array of strings |
{- "addCustomAttributes": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "updateCustomAttributes": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "removeCustomAttributes": [
- "string"
]
}Grant points (and optionally badges) to an advocate identified by email. Use a sensible reason
string — it shows up in the advocate's points history and in admin audit logs.
Common use cases: bonus award, custom one-off recognition, retroactive correction after a missed
activity. For automatic point-per-activity recognition, prefer wiring an activity type with a
points reward and calling Trigger activity instead.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/points/grant-points' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"email": "ada@example.com",
"points": 250,
"reason": "Spoke on the customer panel at SaaSCon 2026"
}'
| email required | string <email> non-empty |
| points required | integer <int32> |
| credit | integer <int32> |
| reason required | string non-empty |
{- "email": "user@example.com",
- "points": 0,
- "credit": 0,
- "reason": "string"
}Get custom attribute values for one or more advocates. Pass a comma-separated list of advocate
UUIDs as uuids; omit to return values for all advocates in the company (use with care on large
tenants).
The response is a map keyed by advocate UUID; each value is an array of attribute readings.
Combine with List custom attributes (entity=contact) to interpret what each attribute means.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/advocate/custom-attributes?uuids=550e8400-e29b-41d4-a716-446655440000,550e8400-e29b-41d4-a716-446655440001' \
-H 'Authorization: Bearer <jwt_token>'
| uuids | string Optional comma-separated list of advocate UUIDs to filter by |
Update one or more custom attribute values on a single advocate identified by email. The request
carries an array of {attributeName, values} rows — each row sets the values of one custom
attribute (values is always an array; for single-value attributes pass a one-element array).
The response is an array of per-update result rows. Either attributeName or attributeUuid
may be used to identify the attribute. Use the per-advocate-id variant (PUT /advocate/custom-attributes/{id}) when you already have the SSO auth id rather than the email.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/advocate/custom-attributes' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"email": "ada@example.com",
"attributes": [
{ "attributeName": "favorite_color", "values": ["blue"] },
{ "attributeName": "role", "values": ["VP Engineering"] }
]
}'
Array of objects (AttributeUpdateDTO) | |
| email required | string <email> non-empty |
{- "attributes": [
- {
- "attributeUuid": "string",
- "values": [
- "string"
], - "attributeName": "string"
}
], - "email": "user@example.com"
}Update custom attribute values for a single advocate identified by external auth id. The payload is partitioned into three maps so a single call can add, update, and remove attributes atomically:
addCustomAttributes — { "<attributeName>": ["value1", "value2"] } — add the given values
(no-op if the attribute already holds them).updateCustomAttributes — { "<attributeName>": ["value1", "value2"] } — replace the
attribute's full value set with the supplied array.removeCustomAttributes — ["<attributeName>", ...] — remove the attribute entirely.The response returns the resulting list of attribute values on the advocate. The companion
PUT /advocate/custom-attributes endpoint targets the advocate by email + a flat
[{attributeName, values}] array — use whichever identifier you already have on hand.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/advocate/custom-attributes/auth0|abcd1234' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"updateCustomAttributes": { "favorite_color": ["green"] }
}'
| id required | string External auth id of the advocate |
object | |
object | |
| removeCustomAttributes | Array of strings |
{- "addCustomAttributes": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "updateCustomAttributes": {
- "property1": [
- "string"
], - "property2": [
- "string"
]
}, - "removeCustomAttributes": [
- "string"
]
}List users (advocates) in the caller's company. Pass emails (comma-separated set) to look up
specific advocates by email. Returns a basic projection — for full advocate data including custom
attributes and consent, use List advocates instead.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/users?emails=ada@example.com,alan@example.com&page=0&size=20' \
-H 'Authorization: Bearer <jwt_token>'
| emails | Array of strings unique Optional set of emails to filter by |
required | object (Pageable) |
Create a new advocate user in the caller's company. Email is unique per company — if the email
already exists in this company the response is 400 with body EMAIL_CONFLICT.
The new user is created in an unactivated state; standard onboarding flows (invitation email,
activation link) fire automatically. Use Import contacts by email for bulk onboarding instead
of looping on this endpoint.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/users' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"email": "ada@example.com",
"firstName": "Ada",
"lastName": "Lovelace",
"jobTitle": "Chief Computing Officer"
}'
| accountName | string |
| firstName required | string non-empty |
| lastName | string |
| captcha | string |
| email required | string <email> non-empty |
| login | string |
| customEmailMessage | string |
| fromRegisterLead | boolean |
| register | boolean |
| muteRegisterEmail | boolean |
| bonusPoints | integer <int32> |
| authId | string |
| companyUuid | string |
| targetCrowdId | string |
| traceUuid | string |
| utmId | string |
| utmSource | string |
| anonymousAdvocateUuid | string |
| advocateTimezoneOffset | integer <int32> |
| joinMethod | string Enum: "INVITE" "REQUEST" "AUTO_SIGNUP" "REFERRAL" "IMPORT" "SSO" "NOMINATE" "API" "INTEGRATION" "DATA_SYNC" |
object (NominationDetails) |
{- "accountName": "string",
- "firstName": "string",
- "lastName": "string",
- "captcha": "string",
- "email": "user@example.com",
- "login": "string",
- "customEmailMessage": "string",
- "fromRegisterLead": true,
- "register": true,
- "muteRegisterEmail": true,
- "bonusPoints": 0,
- "authId": "string",
- "companyUuid": "string",
- "targetCrowdId": "string",
- "traceUuid": "string",
- "utmId": "string",
- "utmSource": "string",
- "anonymousAdvocateUuid": "string",
- "advocateTimezoneOffset": 0,
- "joinMethod": "INVITE",
- "nominationDetails": {
- "nominationRequestMode": "MANAGED",
- "requestByName": "string"
}
}Trigger a tracked activity for an advocate identified by email. The activity is recorded against the advocate and may award points, progress an open ASK, fire downstream automation, or all three depending on how the activity type is configured in admin.
Common patterns: a CRM sync calling this when an opportunity closes, a content platform calling
it when an advocate posts a review, a webhook bridge translating third-party events into Base
activities. Use List activity types to discover valid activity types beforehand.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/trigger-activity' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"email": "ada@example.com",
"apiIdentifier": "case_study_published"
}'
| email required | string <email> non-empty |
| apiIdentifier | string^[a-z0-9_]{1,50}$ |
{- "email": "user@example.com",
- "apiIdentifier": "string"
}Confirm that an advocate directed from the Base system completed registration. Call this from your registration landing page after the advocate's account is provisioned so Base can attribute the registration to the originating UTM campaign and capture profile fields submitted on the form.
utmCampaign is required and is the campaign id Base appended to the registration URL as
?utm_campaign=<id>. Other fields (firstName, lastName, jobTitle, tags, etc.) are optional and
fall back to whatever was supplied earlier in the flow.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/registration-confirmation' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"utmCampaign": "spring-2026-launch",
"step": 2,
"utmSource": "linkedin",
"tags": ["enterprise", "early-adopter"],
"firstName": "Ada",
"lastName": "Lovelace",
"company": "Analytical Engines Inc.",
"jobTitle": "Chief Computing Officer",
"email": "ada@example.com"
}'
| utmCampaign required | string |
| step required | integer <int32> [ 2 .. 3 ] |
| advocateUuid | string |
| utmSource | string |
| tags | Array of strings |
| firstName | string |
| lastName | string |
| company | string |
| jobTitle | string |
string |
{- "utmCampaign": "string",
- "step": 2,
- "advocateUuid": "string",
- "utmSource": "string",
- "tags": [
- "string"
], - "firstName": "string",
- "lastName": "string",
- "company": "string",
- "jobTitle": "string",
- "email": "string"
}Create or update one or more opportunities and their custom attribute values in a single call.
The request body wraps a list of opportunity items; each item is identified by opportunityId
(the external CRM id, required). If no matching opportunity exists in Base the item creates one;
otherwise it updates the existing one in place.
Typical use: a CRM sync job that pushes the latest opportunity state into Base. customAttributes
follows the same [{attributeName, values}] shape used elsewhere in the V1 API.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/opportunity-attributes' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"opportunities": [
{
"opportunityId": "006Aa00001ABcDE",
"opportunityName": "Acme renewal — FY26",
"opportunityStage": "Closed Won",
"opportunityAmount": 75000,
"opportunityProbability": 100,
"opportunityIsWon": true,
"opportunityCloseDate": "2026-05-15",
"customAttributes": [
{ "attributeName": "renewal_reason", "values": ["Expansion"] }
]
}
]
}'
Array of objects (OpportunityUpdateRequestBodyDTO) |
{- "opportunities": [
- {
- "opportunityId": "string",
- "opportunityName": "string",
- "opportunityStage": "string",
- "opportunityAmount": 0.1,
- "opportunityProbability": 100,
- "opportunityIsWon": true,
- "opportunityCloseDate": "2019-08-24",
- "customAttributes": [
- {
- "attributeUuid": "string",
- "values": [
- "string"
], - "attributeName": "string"
}
]
}
]
}Import reference advocates — advocates designated to act as references for sales conversations — by external CRM contact id. Returns per-row results.
Distinct from regular Import contacts by contact ID: the imported records are flagged as
available for the reference-request flow even if they are not active advocates in the usual
points-and-asks sense.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/advocate/reference/import-by-contact-id' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '[
{ "contactId": "003Aa00001ABcDE", "frequency": "ANYTIME" },
{ "contactId": "003Aa00001ABcDF" }
]'
| contactId required | string non-empty |
| register | boolean |
| sendInvite | boolean |
Array of objects (ExternalConsentDTO) | |
| referencePool | string |
| frequency | string |
[- {
- "contactId": "string",
- "register": true,
- "sendInvite": true,
- "consents": [
- {
- "activityTypeId": "string",
- "consent": true,
- "frequency": "string",
- "classification": "string"
}
], - "referencePool": "string",
- "frequency": "string"
}
]Import advocates by email. Each item is processed independently; the response is an array of per-row outcomes.
Email is matched case-insensitively against existing advocates — duplicate rows are surfaced as per-row errors rather than dropped silently. Use for bulk onboarding when email is the only durable identifier you have for the source records.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/advocate/import-by-email' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '[
{
"email": "ada@example.com",
"firstName": "Ada",
"lastName": "Lovelace",
"accountName": "Analytical Engines Inc.",
"register": true,
"sendInvite": false
}
]'
| email required | string <email> [ 0 .. 127 ] characters |
| firstName required | string [ 0 .. 50 ] characters |
| lastName required | string [ 0 .. 50 ] characters |
| accountName required | string [ 0 .. 255 ] characters |
| register | boolean |
| sendInvite | boolean |
Array of objects (ExternalConsentDTO) | |
| referencePool | string |
[- {
- "email": "user@example.com",
- "firstName": "string",
- "lastName": "string",
- "accountName": "string",
- "register": true,
- "sendInvite": true,
- "consents": [
- {
- "activityTypeId": "string",
- "consent": true,
- "frequency": "string",
- "classification": "string"
}
], - "referencePool": "string"
}
]Import advocates by external CRM contact id. Each item in the request body is processed independently — failures on one row do not abort the rest. The response is an array of per-row outcomes (success with new advocate UUID, or per-row error).
Use for bulk onboarding from a CRM where the contact id is the durable identifier. Pair with
Import contacts by email when some rows lack a CRM id but have a verified email.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/advocate/import-by-contact-id' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '[
{ "contactId": "003Aa00001ABcDE", "register": true, "sendInvite": false },
{ "contactId": "003Aa00001ABcDF" }
]'
| contactId required | string non-empty |
| register | boolean |
| sendInvite | boolean |
Array of objects (ExternalConsentDTO) | |
| referencePool | string |
[- {
- "contactId": "string",
- "register": true,
- "sendInvite": true,
- "consents": [
- {
- "activityTypeId": "string",
- "consent": true,
- "frequency": "string",
- "classification": "string"
}
], - "referencePool": "string"
}
]Retrieve a paginated list of accounts (with their core fields and custom attribute values).
Optionally narrow the result to specific accounts via uuids (up to 500 per request). Repeat
the parameter (uuids=A&uuids=B) or pass a comma-separated value (uuids=A,B) — both are
accepted by the Spring binding.
Maximum page size is 500. Use for CRM-sync workflows that need to mirror Base account state back to another system.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/account?uuids=550e8400-e29b-41d4-a716-446655440000&uuids=550e8400-e29b-41d4-a716-446655440001&page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
| uuids | Array of strings [ 0 .. 500 ] items Optional list of up to 500 account UUIDs to filter by |
required | object (Pageable) |
Create or update an account ("upsert"). At least one of uuid or name must be supplied — when
only name is supplied a new account is created if no match exists, otherwise the existing
matching account is updated.
Other fields are optional: domain (lowercase hostname like example.com), sizeFrom / sizeTo
(numeric employee-count range), industryType (free-form), and customAttributeValues as a list
of {name, values} rows for any custom attributes defined on the account entity.
Example (create new account):
curl -X POST 'https://prod.customershome.com/acauth/api/v1/account' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"name": "Analytical Engines Inc.",
"domain": "analyticalengines.com",
"sizeFrom": 100,
"sizeTo": 500,
"industryType": "Software",
"customAttributeValues": [
{ "name": "tier", "values": ["Enterprise"] }
]
}'
| uuid | string |
| name | string |
| domain | string^([a-z0-9]+(-[a-z0-9]+)*\.)+[a-z]{2,6}$ |
| sizeFrom | integer <int32> |
| sizeTo | integer <int32> |
| industryType | string |
Array of objects (CustomDataAttributeValueDTO) |
{- "uuid": "string",
- "name": "string",
- "domain": "string",
- "sizeFrom": 0,
- "sizeTo": 0,
- "industryType": "string",
- "customAttributeValues": [
- {
- "name": "string",
- "values": [
- "string"
]
}
]
}List users (advocates) filtered by source external system and an optional modified-since cutoff.
Designed for incremental sync: poll with sinceLastModified set to the previous successful sync
timestamp to fetch only the diff.
externalSystem is required and identifies which integration sourced the users (CRM, marketing
automation, etc.).
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/users-by-dates?externalSystem=SalesForce&sinceLastModified=2026-05-01T00:00:00&page=0&size=100' \
-H 'Authorization: Bearer <jwt_token>'
| externalSystem required | string Enum: "SalesForce" "HubSpot" "Oracle" "External" "Test" External system identifying the source of users to filter |
| sinceLastModified | string <date-time> Optional ISO 8601 cutoff; only users modified at or after this time are returned |
required | object (Pageable) |
Returns basic status information including the caller's company name. Use this as a cheap connectivity / auth check from your integration before issuing real requests — a 200 response confirms the bearer token is valid and bound to a company.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/status' \
-H 'Authorization: Bearer <jwt_token>'
Retrieve a paginated list of opportunities (with their core fields and custom attribute values).
Optionally narrow to specific opportunities via uuids (up to 500 per request). Repeat the
parameter (uuids=A&uuids=B) or pass a comma-separated value (uuids=A,B).
Maximum page size is 500. Use for CRM-sync workflows that need to read Base's opportunity state.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/opportunity?uuids=550e8400-e29b-41d4-a716-446655440000&page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
| uuids | Array of strings [ 0 .. 500 ] items Optional list of up to 500 opportunity UUIDs to filter by |
required | object (Pageable) |
Read an opportunity and its custom attribute values by external CRM opportunity id (not the Base internal UUID). Useful when your CRM is the source of truth and you want to verify what Base currently has stored.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/opportunity-attributes/006Aa00001ABcDE' \
-H 'Authorization: Bearer <jwt_token>'
| id required | string External (CRM) opportunity id |
Retrieve a paginated leaderboard of advocates ranked by points (highest first). Set
email=true to include each advocate's email in the response — by default it is omitted so the
payload is safe to embed in a public-facing UI.
Use Spring pagination (page, size) to walk the leaderboard; the underlying ordering is stable
across pages.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/leaderboard?page=0&size=20' \
-H 'Authorization: Bearer <jwt_token>'
boolean Whether to include email addresses for each advocate (default false) | |
required | object (Pageable) |
Return the leaderboard entry for a single advocate identified by email. Useful when embedding an advocate's own rank/points in an in-product widget without walking the full leaderboard.
Returns 404 if the advocate or company cannot be resolved.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/leaderboard-by-email?email=ada@example.com' \
-H 'Authorization: Bearer <jwt_token>'
| email required | string Email of the advocate to look up |
Retrieve a paginated list of ASKs defined in the company. (ASK is the customer-facing label for
what the API calls challenge — see the intro for the terminology mapping.)
Maximum page size is 500. Returns active and inactive ASKs alike; filter by status / type on the client side if needed.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/challenge?page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
required | object (Pageable) |
Retrieve a paginated list of advocates with their account and consent information. Optionally filter by a single advocate UUID or email.
Maximum page size is 500; requests above that limit return 400. Use this rather than List users
when you need account linkage, custom attribute values, or consent flags. Combine with since-style
filtering on related endpoints for incremental sync into your CRM.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/advocate?email=ada@example.com&page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
| uuid | string Optional advocate UUID to filter to a single record |
string Optional advocate email to filter to a single record | |
required | object (Pageable) |
Read custom object records and their attribute values for one advocate. Identify the advocate by
UUID or email (one of the two is required); identify the custom object type by objectName (its
apiName from the mapping).
Without instanceId, returns every record of that object type attached to the advocate.
With instanceId, narrows the response to a single record. Use the listing form first to discover
instance IDs, then drill in for the data you need.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/advocate/custom-object-record/subscription?advocateEmail=ada@example.com' \
-H 'Authorization: Bearer <jwt_token>'
| objectName required | string API name of the custom object |
| advocateUuid | string UUID of the target advocate (either advocateUuid or advocateEmail is required) |
| advocateEmail | string Email of the target advocate (either advocateUuid or advocateEmail is required) |
| instanceId | string Optional instance ID to narrow to a specific custom object record |
List external-entity field values for selected custom attribute fields across advocates. Use
fieldNames to scope the query to specific attributes and sinceLastModified (ISO-8601 UTC) to
fetch only the values that changed at or after that time.
Designed for incremental sync: poll with sinceLastModified = "last successful sync timestamp"
to pull only the diff rather than the full universe of values.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/advocate/custom-attributes/field-value?fieldNames=favorite_color,role&sinceLastModified=2026-05-01T00:00:00Z&page=0&size=100' \
-H 'Authorization: Bearer <jwt_token>'
| fieldNames | Array of strings Optional list of custom attribute field names to return |
| sinceLastModified | string <date-time> Optional ISO 8601 cutoff; only field values modified at or after this time are returned |
required | object (Pageable) |
Retrieve a paginated list of activity records (advocate actions tracked by Base). Each activity references an advocate, an activity type, and a timestamp. Use for analytics export or to populate an activity feed in your own UI.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/activity?page=0&size=50' \
-H 'Authorization: Bearer <jwt_token>'
required | object (Pageable) |
Return all activity types defined in the caller's company. Each activity type has a stable name
that you pass to Trigger activity.
Cache the result on your side — activity types change rarely (admin configuration), and calling this on every Trigger activity request is wasteful.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/activity-types' \
-H 'Authorization: Bearer <jwt_token>'
Delete an advocate by external auth id (the SSO-issued identifier). Same security/no-enumeration
semantics as Delete user by email: returns 204 for both "deleted" and "not found". A 500
indicates the delete itself failed downstream. The deletion is permanent.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/users-by-id?id=auth0|abcd1234' \
-H 'Authorization: Bearer <jwt_token>'
| id required | string External auth id of the user to delete |
Delete an advocate by email. For security reasons the endpoint does not disclose whether the user existed — it returns 204 No Content for both "deleted" and "not found" to prevent email enumeration. A 500 indicates the delete itself failed downstream.
The deletion cascades to consent records, custom attribute values, points history, and ASK progress; the advocate cannot be recovered.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/users-by-email?email=ada@example.com' \
-H 'Authorization: Bearer <jwt_token>'
| email required | string Email of the user to delete |
Define and manage custom object types (mappings) and the attributes on those objects.
Update the human-readable label/description of an existing custom object mapping. The apiName,
owning entity, and the attributes defined on the object are immutable via this endpoint — use
the Custom Attributes endpoints to add or remove fields.
Example:
curl -X PUT 'https://prod.customershome.com/acauth/api/v1/custom-object-mapping/primary_contact' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"label": "Primary contact",
"description": "Updated description"
}'
| apiName required | string API name of the mapping to update |
| label required | string [ 1 .. 128 ] characters Human-readable label for the custom object |
| description | string [ 0 .. 100 ] characters Optional description (max 100 characters) |
{- "label": "Primary Contact",
- "description": "Primary point of contact at the account"
}Delete a custom object mapping by apiName. All records of this custom object type across every
advocate/account/opportunity in the company are deleted along with their attribute values.
Irreversible — use with care.
Example:
curl -X DELETE 'https://prod.customershome.com/acauth/api/v1/custom-object-mapping/primary_contact' \
-H 'Authorization: Bearer <jwt_token>'
| apiName required | string API name of the mapping to delete |
List custom object mappings (and their attributes) for a given entity. A "mapping" describes a
custom object type (e.g. primary_contact, subscription) that you can attach to advocates,
accounts, or opportunities.
Use this to discover what custom object types are available before creating / reading records.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/custom-object-mapping?entity=account' \
-H 'Authorization: Bearer <jwt_token>'
| entity required | string Enum: "contact" "account" "opportunity" "nomination" Entity owning the custom objects (advocate, account, opportunity, etc.) |
Define a new custom object mapping on an entity. apiName is the immutable identifier used in all
subsequent record-level calls (URL path parameter, query payloads), so choose carefully — typically
lowercase singular noun like subscription or meeting. label is the human-readable display
used in admin UIs.
After this returns, define the attributes on the new custom object via Create Custom Attribute
(with entity set to the new mapping's apiName).
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/custom-object-mapping' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"apiName": "primary_contact",
"label": "Primary Contact",
"description": "Primary point of contact at the account",
"entity": "account"
}'
| label required | string [ 1 .. 128 ] characters Human-readable label for the custom object |
| description | string [ 0 .. 100 ] characters Optional description (max 100 characters) |
| apiName required | string [ 1 .. 64 ] characters ^(?!.*\s)[a-z0-9_]+$ Internal API name. 1 to 64 characters, lowercase letters/digits/underscores only. |
| entity required | string Enum: "contact" "account" "opportunity" "nomination" Entity that owns this custom object |
{- "label": "Primary Contact",
- "description": "Primary point of contact at the account",
- "apiName": "primary_contact",
- "entity": "contact"
}List attributes that exist on a custom object related to a given entity. entityRelation is the
relation key declared when the custom object was mapped (e.g. primary_contact for a Contact
object related to an Account).
Returned by Get Account Custom Object Attribute Values / advocate equivalent before you read or
write per-record values.
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/custom-object-attributes?entityRelation=primary_contact' \
-H 'Authorization: Bearer <jwt_token>'
| entityRelation required | string Relation name identifying the custom object on the entity |
Retrieve a paginated list of reference requests matching the provided filter (deadline range, statuses, requester, etc.). Use this for reporting dashboards or to find the UUID of a specific request to read in detail.
Maximum page size is 100. Sort using the standard Spring sort query parameter
(e.g. sort=createdAt,desc).
Example:
curl -X GET 'https://prod.customershome.com/acauth/api/v1/reference-requests?page=0&size=50&sort=createdAt,desc' \
-H 'Authorization: Bearer <jwt_token>'
required | object (ReferenceRequestFilterDTO) Filter criteria for narrowing the result set: date range, statuses, requester, etc. See |
| size required | integer <int32> [ 1 .. 100 ] |
| page required | integer <int32> >= 0 |
required | object (Pageable) |
Submit a new reference request. The body must specify an opportunity, opportunity contact, requester, reference manager, and 1–10 reference entries. All entries must be the same type — either all source-contact (sourced from your CRM) or all P2P (an existing advocate acting as reference). Mixed types are rejected.
Returns 204 No Content on success; downstream notifications and workflows pick up the request asynchronously.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/reference-requests' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"deadline": "2026-06-01T00:00:00Z",
"subject": "Reference for Acme renewal",
"referenceTypeUuid": "550e8400-e29b-41d4-a716-446655440000",
"notes": "Looking for a 30-minute peer reference call.",
"opportunity": {
"opportunityId": "006Aa00001ABcDE",
"opportunityName": "Acme renewal — FY26",
"opportunityAccountId": "001Aa00001A2B3C",
"opportunityAccountName": "Acme Corp"
},
"opportunityContact": {
"externalId": "003Aa00001ABcDE",
"firstName": "Bob",
"lastName": "Buyer",
"email": "buyer@acme.example"
},
"requester": {
"externalId": "005Aa00001ZyXwV",
"firstName": "Sara",
"lastName": "Sales",
"email": "rep@yourcompany.example"
},
"referenceManager": { "uuid": "660e8400-e29b-41d4-a716-446655440111" },
"entries": [
{
"externalId": "rr-2026-q2-001",
"crmRequestNumber": "REQ-12345",
"advocate": { "uuid": "770e8400-e29b-41d4-a716-446655440222" }
}
]
}'
| deadline required | string <date-time> Deadline by which the reference should be completed |
| subject required | string Short subject line describing the reference request |
| referenceTypeUuid required | string UUID of the reference type (e.g. case study, peer call) from the form configuration |
| notes | string Internal-only notes shown to the reference manager / sales team |
| notesForReference | string Notes shown to the reference advocate when invited |
required | object (OpportunityDTO) Opportunity the reference is requested for |
required | object (ExternalActorDTO) Contact person on the opportunity (typically the buyer) |
required | object (ExternalActorDTO) Person who requested the reference (salesperson in CRM) |
required | object (BaseActorDTO) Reference manager assigned to coordinate the request |
required | Array of objects (RequestEntryDTO) [ 1 .. 10 ] items 1–10 reference entries; all must be source-contact OR all P2P (cannot be mixed) |
Array of objects (ReportCustomAttributesFiltersDTO) Optional custom-attribute filters captured at request time (used by the custom-element reference form) |
{- "deadline": "2026-06-01T00:00:00Z",
- "subject": "Reference for Acme renewal",
- "referenceTypeUuid": "string",
- "notes": "string",
- "notesForReference": "string",
- "opportunity": {
- "opportunityId": "string",
- "opportunityName": "string",
- "opportunityStage": "string",
- "opportunityAmount": 0.1,
- "opportunityProbability": 0,
- "opportunityIsWon": true,
- "opportunityCloseDate": "2019-08-24",
- "opportunityAccountId": "string",
- "opportunityAccountName": "string"
}, - "opportunityContact": {
- "externalId": "string",
- "firstName": "string",
- "lastName": "string",
- "email": "user@example.com",
- "name": "string"
}, - "requester": {
- "externalId": "string",
- "firstName": "string",
- "lastName": "string",
- "email": "user@example.com",
- "name": "string"
}, - "referenceManager": {
- "uuid": "string"
}, - "entries": [
- {
- "externalId": "string",
- "crmRequestNumber": "string",
- "advocate": {
- "uuid": "string"
}
}
], - "matchCriteria": [
- {
- "id": "string",
- "name": "string",
- "entity": "string",
- "minValue": null,
- "maxValue": null,
- "values": [
- "string"
], - "addedBySystem": true,
- "weight": 0,
- "filterValuesPresent": true
}
]
}Retrieve the configuration of the reference request form: which fields are enabled, their labels,
available reference types, allowed reference managers, custom attributes to display, and contact /
weighting options. The configuration is computed from the supplied context — pass the CRM
account, opportunity, and intended reference type so the response reflects the rules that apply
to that specific combination.
Call this first to render the form UI or to know which fields are valid before submitting a reference request.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/reference-requests/form' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"context": {
"account": { "id": "001Aa00001A2B3C", "name": "Acme Corp", "industry": "Software" },
"opportunity": { "id": "006Aa00001ABcDE", "name": "Acme renewal — FY26", "accountId": "001Aa00001A2B3C", "stage": "Negotiation" },
"referenceTypeUuid": "550e8400-e29b-41d4-a716-446655440000"
}
}'
object (ReferenceRequestContext) Context in which the form is being requested (controls which fields/options are returned) |
{- "context": {
- "account": {
- "id": "string",
- "name": "string",
- "domain": "string",
- "type": "string",
- "industry": "string",
- "location": "string",
- "numberOfEmployees": 0,
- "customDataAttributes": {
- "property1": null,
- "property2": null
}
}, - "opportunity": {
- "id": "string",
- "name": "string",
- "accountId": "string",
- "amount": 0.1,
- "stage": "string",
- "probability": 0.1,
- "isWon": true,
- "closeDate": "string",
- "customDataAttributes": {
- "property1": null,
- "property2": null
}
}, - "referenceTypeUuid": "string"
}
}Retrieve a paginated list of advocates eligible to be referenced, ranked by the weighted criteria supplied in the request body. Use this to pre-populate a "best matches" list when building a reference request UI, or to feed an internal sales-tooling dashboard.
Maximum page size is 100. The weighting model considers industry / role overlap, recent activity, consent, and any custom attribute filters you pass.
Example:
curl -X POST 'https://prod.customershome.com/acauth/api/v1/reference-advocates/report?page=0&size=20' \
-H 'Authorization: Bearer <jwt_token>' \
-H 'Content-Type: application/json' \
-d '{
"industryTypes": { "value": [12, 47], "weight": 5 },
"jobTitles": { "value": ["VP Engineering"], "weight": 4 },
"accountSizeFrom": { "value": 100, "weight": 2 },
"accountSizeTo": { "value": 5000, "weight": 2 },
"customAttributes": [
{
"id": "aa11bb22-cc33-dd44-ee55-ff6677889900",
"name": "favorite_color",
"entity": "contact",
"values": ["blue"],
"weight": 1
}
],
"referenceTypeUuid": "550e8400-e29b-41d4-a716-446655440000",
"reportSize": 50
}'
| size required | integer <int32> [ 1 .. 100 ] |
| page required | integer <int32> >= 0 |
required | object (Pageable) |
object (WeightedFilterParameterDTOListLong) | |
object (WeightedFilterParameterDTOListLong) | |
object (WeightedFilterParameterDTOListLong) | |
object (WeightedFilterParameterDTOListString) | |
object (WeightedFilterParameterDTOLong) | |
object (WeightedFilterParameterDTOLong) | |
object (WeightedFilterParameterDTOListString) | |
object (WeightedFilterParameterDTOListString) | |
| includeGroupedAttributes | boolean |
Array of objects (ReportCustomAttributesFiltersDTO) | |
object | |
| challengeUuid | string |
| advocateUuid | string |
| opportunityId | string |
object (WeightedFilterParameterDTOListString) | |
| hasExternalId | boolean |
| referenceTypeUuid | string |
| searchCriteria | string |
| reportSize | integer <int32> |
{- "seniorityLevels": {
- "weight": 0,
- "value": [
- 0
]
}, - "geographicalLocations": {
- "weight": 0,
- "value": [
- 0
]
}, - "industryTypes": {
- "weight": 0,
- "value": [
- 0
]
}, - "jobTitles": {
- "weight": 0,
- "value": [
- "string"
]
}, - "accountSizeFrom": {
- "weight": 0,
- "value": 0
}, - "accountSizeTo": {
- "weight": 0,
- "value": 0
}, - "productsAndServices": {
- "weight": 0,
- "value": [
- "string"
]
}, - "useCases": {
- "weight": 0,
- "value": [
- "string"
]
}, - "includeGroupedAttributes": true,
- "customAttributes": [
- {
- "id": "string",
- "name": "string",
- "entity": "string",
- "minValue": null,
- "maxValue": null,
- "values": [
- "string"
], - "addedBySystem": true,
- "weight": 0,
- "filterValuesPresent": true
}
], - "customObjectAttributes": {
- "property1": [
- {
- "id": "string",
- "name": "string",
- "entity": "string",
- "minValue": null,
- "maxValue": null,
- "values": [
- "string"
], - "addedBySystem": true,
- "weight": 0,
- "filterValuesPresent": true
}
], - "property2": [
- {
- "id": "string",
- "name": "string",
- "entity": "string",
- "minValue": null,
- "maxValue": null,
- "values": [
- "string"
], - "addedBySystem": true,
- "weight": 0,
- "filterValuesPresent": true
}
]
}, - "challengeUuid": "string",
- "advocateUuid": "string",
- "opportunityId": "string",
- "referenceAdvocateScores": {
- "weight": 0,
- "value": [
- "string"
]
}, - "hasExternalId": true,
- "referenceTypeUuid": "string",
- "searchCriteria": "string",
- "reportSize": 0
}