Download OpenAPI specification:
A list of selected endpoints for Apricot API, to be used by the Bonterra API
Retrieves a list of all users in your Apricot instance. Pagination (page[size]) is
required; filtering and sorting are optional.
Common use cases:
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys | |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
curl -X GET "https://api.bonterra.network/v1/apricot/users?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}Creates a new user account in Apricot. Requires username, first name, last name, and user type.
Common use cases:
Important notes:
site_admins_enabled and the new user is not an Admin, a non-empty
site_links array is required or the request fails with a 400| Authorization required | string Header that carries token for request Authorization |
| type required | string Resource type, must be 'users' |
object User attributes |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
{- "type": "users",
- "attributes": {
- "username": "john.doe@bonterratech.com",
- "password": "SecureP@ssw0rd123",
- "name_first": "John",
- "name_middle": "Michael",
- "name_last": "Doe",
- "user_type": "Standard"
}
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}What it does: Retrieves the profile information for the currently authenticated user based on the access token. This is a self-service endpoint that returns details about "you" (the token owner) without needing to know your user ID.
When to use it:
What you'll need:
What you'll get back: Your complete user profile including:
Use cases:
vs. GET /users/{id}:
Important notes:
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
curl -X GET "https://api.bonterra.network/v1/apricot/users/info" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
| type required | string Resource type, must be 'users' |
object User attributes |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
{- "type": "users",
- "attributes": {
- "username": "john.doe@bonterratech.com",
- "password": "SecureP@ssw0rd123",
- "name_first": "John",
- "name_middle": "Michael",
- "name_last": "Doe",
- "user_type": "Standard"
}
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}Retrieves all Apricot organizations that a Bonterra Auth user is linked to. This endpoint is used for authorization purposes by Account and Impact Hub services.
Purpose:
Personas:
Important notes:
orgsis_super_user being true does not imply an empty orgs array - a super user with real active
organization memberships will still have them listed| bonterra_auth_id required | string Example: 37f9a9b0-76ac-4d13-a3b4-8eb9873a24f5 Bonterra Auth ID (GUID, e.g., 37f9a9b0-76ac-4d13-a3b4-8eb9873a24f5) |
| Authorization required | string Header that carries token for request Authorization |
required | Array of objects (ApricotUserOrganizationMembership) Array of organization memberships. Each item represents the user's relationship with an organization. Empty array if user has no organizations. |
| bonterra_auth_id required | string The Bonterra Auth user ID |
| is_super_user | boolean Indicates the caller is a super user. Only present (and only ever |
{- "bonterra_auth_id": "37f9a9b0-76ac-4d13-a3b4-8eb9873a24f5",
- "orgs": [
- {
- "org_id": "12345",
- "org_name": "Acme Foundation",
- "user_id": "789",
- "user_email": "user@example.com",
- "user_first_name": "John",
- "user_last_name": "Doe",
- "user_type": "Administrator",
- "locked": false,
- "locked_reason": "Unlocked"
}, - {
- "org_id": "67890",
- "org_name": "Global Charity Network",
- "user_id": "456",
- "user_email": "user@example.com",
- "user_first_name": "John",
- "user_last_name": "Doe",
- "user_type": "Standard",
- "locked": true,
- "locked_reason": "User is inactive"
}
]
}What it does: Retrieves a list of all users who have been granted access to a specific program. This helps you manage program-level permissions and understand who can view/edit data within a program.
When to use it:
What you'll need:
page[size] is required); sorting and filtering are optionalWhat you'll get back: Array of user objects with access to this program, each containing:
user_type (e.g. Administrator, Standard User, Guest), which determines permissions level - there is no separate scalar role fieldInactive users are always excluded from the results; there is no way to opt in to seeing them.
Common use cases:
Note: This returns users with explicit program access. System administrators may have access to all programs without being explicitly listed.
| id required | integer <int32> |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
curl -X GET "https://api.bonterra.network/v1/apricot/programs/2/users?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}Retrieves a list of all programs in your Apricot instance. Programs are used to organize records and users by service type or department.
Common use cases:
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
Array of objects (ApricotProgram) Array of program objects |
curl -X GET "https://api.bonterra.network/v1/apricot/programs?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does: Creates a new program in your Apricot instance. Programs are the top-level organizational structure used to group related forms, records, and users. Each program typically represents a distinct service area, grant-funded initiative, or department.
When to use it:
What you'll need:
What you'll get back: The newly created program object including:
Important notes:
active field is ignored/overridden on creationCommon program types:
Program data for the new program
required | object |
Array of objects (ApricotProgram) Array of program objects |
{- "data": {
- "type": "programs",
- "attributes": {
- "name": "Emergency Financial Assistance 2025",
- "description": "Short-term financial assistance for emergency needs including rent, utilities, and medical costs",
- "site_id": 1
}
}
}{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does: Retrieves detailed information about a specific program. Programs in Apricot are organizational containers that group related forms, records, and users together, representing distinct service areas or organizational divisions.
When to use it:
What you'll need:
What you'll get back: Complete program object including:
Program hierarchy: Programs can contain multiple forms, and each form can contain multiple records. Understanding the program structure is essential for proper data organization.
| id required | integer <int32> |
Array of objects (ApricotProgram) Array of program objects |
curl -X GET "https://api.bonterra.network/v1/apricot/programs/2" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does: Updates an existing program's properties. You can modify the program name, description, active status, and other program-level attributes. This operation performs a partial update, so you only need to include the fields you want to change.
When to use it:
What you'll need:
What you'll get back: The complete updated program object with all fields, including:
Important notes:
id URL path parameter; any id/type values in the request body are ignoredCommon update scenarios:
| id required | integer <int32> |
Program fields to update (partial update supported)
required | object |
Array of objects (ApricotProgram) Array of program objects |
{- "data": {
- "type": "programs",
- "id": "2",
- "attributes": {
- "name": "Youth Services - Updated",
- "description": "Updated comprehensive youth development program",
- "active": 1
}
}
}{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does:
Retrieves the same program object as GET /apricot/programs/{id}, scoped to the caller's
intake-specific permissions rather than their general program-access permissions. It is
intended for Bonterra Connect intake and referral workflows that need to look up an Apricot
program's details before creating a record in it.
When to use it:
What you'll need:
What you'll get back:
The identical program object returned by GET /apricot/programs/{id} (same id, name,
description, active status, referral settings, and other program attributes). There is no
separate "intake format" - the response shape is identical.
Integration scenario:
vs. GET /programs/{id}:
GET /programs/{id} records| id required | integer <int32> |
Array of objects (ApricotProgram) Array of program objects |
curl -X GET "https://api.bonterra.network/v1/apricot/programs/2/intake" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does: Retrieves a list of all users who have been granted access to a specific program. This helps you manage program-level permissions and understand who can view/edit data within a program.
When to use it:
What you'll need:
page[size] is required); sorting and filtering are optionalWhat you'll get back: Array of user objects with access to this program, each containing:
user_type (e.g. Administrator, Standard User, Guest), which determines permissions level - there is no separate scalar role fieldInactive users are always excluded from the results; there is no way to opt in to seeing them.
Common use cases:
Note: This returns users with explicit program access. System administrators may have access to all programs without being explicitly listed.
| id required | integer <int32> |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotUser) Array of user objects |
curl -X GET "https://api.bonterra.network/v1/apricot/programs/2/users?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 1487,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "john.doe@bonterratech.com",
- "user_type": "Administrator",
- "name_first": "John",
- "name_last": "Doe",
- "active": 1,
- "mod_time": "2023-11-18T09:15:00Z"
}, - "links": {
- "self": "/apricot/users/1487"
}
}, - {
- "id": 1488,
- "type": "users",
- "attributes": {
- "org_id": 448,
- "username": "jane.smith@bonterratech.com",
- "user_type": "Standard",
- "name_first": "Jane",
- "name_last": "Smith",
- "active": 1,
- "mod_time": "2023-11-17T15:30:00Z"
}, - "links": {
- "self": "/apricot/users/1488"
}
}
]
}What it does: Creates a copy (clone) of an existing program's attributes and permission sets. This is useful when you need to create a new program with similar settings to an existing one, saving time compared to manually recreating everything from scratch.
When to use it:
What you'll need:
name is omitted, the copy inherits the source program's exact name)What gets copied:
What does NOT get copied:
What you'll get back: The newly created program object including:
Important notes:
name silently produces a duplicate nameCommon scenarios:
| id required | integer <int32> |
New program details for the copy
required | object |
Array of objects (ApricotProgram) Array of program objects |
{- "data": {
- "type": "programs",
- "attributes": {
- "name": "Emergency Financial Assistance 2026",
- "description": "Copy of 2025 program for new grant year"
}
}
}{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}Get a list of all Apricot Programs the caller has intake-scoped access to.
Unlike GET /apricot/programs, which returns 200 with an empty array when there are no
matching programs, this endpoint returns 404 when there are no intake-eligible programs.
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
Array of objects (ApricotProgram) Array of program objects |
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}Retrieves all records for a specific form. Use this endpoint to fetch a list of records that belong to a particular form. Results can be paginated.
Common use cases:
Filtering:
filter[field_<id>]=value performs a SQL LIKE match on that field, where <id> is the
field's numeric ID (e.g. field_2002, discoverable via GET /apricot/forms/{id}/fields) -
not the field's label. The value is passed directly to LIKE, so it supports % as a
wildcard (e.g. filter[field_2002]=John% matches values starting with "John"); a value
with no % matches only that exact string.
PII filtering and field metadata:
pii_filter=true removes PII fields (name, address, email, phone, SSN, photo/signature, etc.) from every record in the response.include_field_metadata=true adds a meta.field_metadata map (keyed by field_<id>, each entry containing id, label, field_type_id, field_type_name) describing the fields present in the response.| form_id required | integer <int32> Example: The ID of the form to query records from |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys | |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
| include | string Example: include=field_1001,field_2_first Comma-separated list of field names to include in the response (e.g. |
| pii_filter | string Enum: "true" "false" Example: pii_filter=true When |
| include_field_metadata | string Enum: "true" "false" Example: include_field_metadata=true When |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
curl -X GET "https://api.bonterra.network/v1/apricot/records?form_id=100&page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \ -H "Content-Type: application/json"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does: Creates a new record in the specified form. This endpoint supports three content types for different use cases, including the ability to create a record with file attachments in a single request.
When to use it:
What you'll need:
What you'll get back: Newly created record with ID and all field values including attachment metadata if files were uploaded
Three Content Type Options:
1. application/json (Most common) Use for creating records without files. Simple JSON body with field values.
2. application/vnd.api+json (JSON API format) Use if your application follows JSON API specification.
3. multipart/form-data (For records with attachments - Option 1) Use when creating a new record AND you have files ready to attach immediately. This is the "Option 1" approach for working with attachments.
Two Approaches for Attachments:
Option 1: Create Record with Attachments (this endpoint with multipart/form-data)
Option 2: Add Attachment to Existing Record
Field Naming Patterns: Field IDs follow specific patterns based on field type:
field_1001, field_1002field_2_first, field_2_lastfield_99_line1, field_99_city, field_99_state, field_99_zipfield_827, field_950 (uploaded as files in multipart/form-data)Important notes:
form_id parameter is required (query parameter or in attributes)How the multipart/form-data body is actually parsed (important):
The multipart parser does not look for a field named data - it has no
special handling for any field name. For every non-file field it receives, it attempts
JSON.parse(value); if that succeeds, the entire request body is replaced with the
parsed result (not merged), regardless of what the field was named. Only if JSON.parse
fails does the parser fall back to setting that one key (req.body[key] = value). This
means:
data) and it will work.data) alongside your file fields.| form_id required | integer <int32> Example: The ID of the form to query records from |
| Authorization required | string Header that carries token for request Authorization |
For JSON requests (application/json or application/vnd.api+json): Send record data as JSON with type and attributes.
For multipart/form-data (creating record with attachments):
data, though the parser does not check the field name)| type required | string Resource type, must be 'records' |
object (ApricotRecordBodyAttributes) Attributes for creating or updating a record. Field names are dynamic based on form definition (e.g., field_1001, field_1002). | |
Array of objects (ApricotRecordBodyMetadata) Optional metadata array to bypass UI validation requirements when creating/updating records | |
| writeMode | string Default: "default" Enum: "default" "import" Controls which internal write path processes the request. |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
{- "type": "records",
- "attributes": {
- "form_id": 2,
- "programs": [
- 2
], - "field_96": "Active",
- "field_2_first": "John",
- "field_2_last": "Doe"
}
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does: Retrieves a single record by its unique identifier. Returns the complete record including all field values, metadata, attachment information, timestamps, and relationships.
When to use it:
What you'll need:
What you'll get back:
A record collection object ({meta, data: [...]}) whose data array contains exactly
one record, with:
Understanding the Response:
Important notes:
| id required | integer <int32> |
object Example: filter[active]=1 Filter parameters to narrow down results. For this endpoint, only |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
curl -X GET "https://api.bonterra.network/v1/apricot/records/123" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does: Updates an existing record with new field values. You can update one field or multiple fields in a single request. Fields not included in the request remain unchanged.
When to use it:
What you'll need:
What you'll get back: Updated record object with all field values (not just the ones you updated)
Two Update Strategies:
Strategy 1: Partial Update (Recommended for most cases) Only send the fields you want to change. Other fields remain unchanged.
Strategy 2: Full Update (Safest for critical data) GET the record first, modify the fields you want, then PUT the complete attributes object.
Important notes:
attributes.form_id doesn't match the record's current form -
records cannot be moved between forms via this endpoint. form_id in the body
must equal the record's existing form_id; a different value is rejected as an error,
not treated as a move.Common Issues:
"Required field missing" error:
Accidentally clearing fields:
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
Update request body containing the fields to modify.
Partial update: Include only the fields you want to change Full update: Include all attributes from GET response with your changes
| type required | string Resource type, must be 'records' |
object (ApricotRecordBodyAttributes) Attributes for creating or updating a record. Field names are dynamic based on form definition (e.g., field_1001, field_1002). | |
Array of objects (ApricotRecordBodyMetadata) Optional metadata array to bypass UI validation requirements when creating/updating records | |
| writeMode | string Default: "default" Enum: "default" "import" Controls which internal write path processes the request. |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
{- "type": "records",
- "attributes": {
- "form_id": 2,
- "field_1002": "newemail@example.com"
}
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}| id required | integer <int32> |
| field_id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
{- "users": [
- {
- "message": "string",
- "code": "string"
}
]
}What it does: Uploads a file attachment to a specific field on an existing record. This is one of two ways to add attachments to records in Apricot.
When to use it:
What you'll need:
What you'll get back: Success response with attachment metadata including file ID, filename, size, and download URL
Two Approaches for Working with Attachments:
Option 1: Create Record with Attachments (multipart/form-data) Use this when creating a new record and you have files ready to attach immediately. See POST /apricot/records with Content-Type: multipart/form-data
Option 2: Add Attachment to Existing Record (this endpoint) Use this endpoint when working with existing records.
Finding Field IDs: To find which field_id to use for attachments:
Example: If you see a field with id: 827 and it's an attachment type, use field_id=827
IMPORTANT - multipart field name: The uploaded file must be sent in a form field
named field_<field_id> (e.g. field_827 for field_id=827), NOT a field named "file".
This is a common and easy mistake: if you send the field named "file" instead, the
upload is silently ignored - the request still returns 200 OK with the record
unchanged, and no file is attached.
Important notes:
Common Issues:
Upload silently ignored (200 OK, record unchanged):
field_<field_id> (e.g. "file"),
or field_id does not correspond to an attachment field on the formfield_<field_id> form field name"Invalid file type" error:
Content-Type header issues:
| id required | integer <int32> |
| field_id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
Upload a file using multipart/form-data. The file must be sent in a form field named
field_<field_id> (e.g. "field_827" when field_id=827) - NOT a field named "file".
Sending the field as "file" causes the upload to be silently ignored (200 OK, no file attached).
Important: Do not set Content-Type header manually - your HTTP client will set it correctly with the multipart boundary.
| field_827 | string <binary> The file to upload (PDF, DOCX, PNG, JPG, etc.). The property name must match
|
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects Array containing the single updated record, re-serialized with type "files" |
{ "field_827": "(binary file data)" }
{- "meta": {
- "count": 1
}, - "data": [
- {
- "id": "123",
- "type": "files",
- "attributes": {
- "form_id": 2,
- "field_827": {
- "filename": "resume.pdf",
- "size": 102400
}
}
}
]
}What it does:
Retrieves, for each link field on the record's form, a summary of how many active and
inactive links exist on that field. This is a count summary, not the linked records
themselves — to retrieve the actual linked record data, use
GET /apricot/records/{id}/links/field/{field_id}.
When to use it:
GET /apricot/records/{id}/links/field/{field_id}What you'll need:
What you'll get back: Collection of link-summary objects, one per link field on the record's form, each containing:
Authorization note: Access is checked against every form referenced by a link field on the record's own form, not just the requested record's own form. A 403 here can originate from a linked form's permissions, not just the requested record's.
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecordLinkSummary) Array of link-summary objects, one per link field on the record's form |
curl -X GET "https://api.bonterra.network/v1/apricot/records/12345/links" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 1
}, - "data": [
- {
- "id": 827,
- "type": "links",
- "attributes": {
- "field_label": "Related Case Records",
- "active_count": 3,
- "inactive_count": 0,
- "form": {
- "id": 100,
- "name": "Case Records",
- "active": 1
}
}, - "links": {
- "self": "/apricot/records/12345/links/field/827"
}
}
]
}What it does:
Retrieves the full linked record objects for a given link field on a record. This is the
endpoint that returns actual linked records; GET /apricot/records/{id}/links only returns
per-field link-count summaries.
When to use it:
What you'll need:
GET /apricot/records/{id}/links for the field IDs and
counts available on a record)What you'll get back:
Collection of linked record objects (same shape as GET /apricot/records), with each
linked record's data additionally including link_description, link_description_label,
link_creation_time, and link_active for the specific link being returned.
| id required | integer <int32> |
| field_id required | integer <int32> |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
curl -X GET "https://api.bonterra.network/v1/apricot/records/12345/links/field/827" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does: Retrieves just the record IDs linked to a record on a given link field, without loading the full linked record data or checking per-record permissions.
Restrictions: This endpoint is restricted to Admin users. Non-admin callers receive a 401, even with a valid access token and the right scope.
What you'll need:
What you'll get back: A count and a plain array of linked record IDs — not a JSON:API resource collection, unlike most other Apricot list endpoints.
| id required | integer <int32> |
| field_id required | integer <int32> |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
| data | Array of integers <int32> [ items <int32 > ] Array of linked record IDs |
curl -X GET "https://api.bonterra.network/v1/apricot/records/12345/links/field/827/ids" \ -H "Authorization: Bearer YOUR_ADMIN_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- 54321,
- 54322
]
}What it does:
Creates an external referral for a record, notifying an external recipient by email.
The only fields accepted are email (the recipient's email address) and notes (free-text
referral notes) - there is no organization name, service type, referral date, contact
person/phone, or status field.
When to use it:
What you'll need:
email: the recipient's email address (required)notes: the referral notes to send (required)can_send_referral); otherwise the
request is rejected with a 403 (non-admin) or 400 (admin)What you'll get back:
The created referral resource (JSON:API type referrals), including status, the
referring/receiving program IDs, and the notes submitted.
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
External referral details
| type | string |
object (ApricotExternalReferralBodyAttributes) |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotReferral) |
{- "type": "referrals",
- "attributes": {
- "email": "referrals@communityhealthcenter.example",
- "notes": "Client needs transportation assistance"
}
}{- "meta": {
- "count": 25,
- "currentPage": 1,
- "numPages": 4,
- "sortBy": "creation_time",
- "sortAsc": true
}, - "data": [
- {
- "id": "1",
- "type": "referrals",
- "attributes": {
- "status": "external",
- "parent_id": 0,
- "form_ids": [
- 0
], - "program_ids_referred_to": {
- "email": "string"
}, - "program_ids_referred_from": [
- 0
], - "sort_order": 0,
- "initial_owner_id": 0,
- "assigned_owner_id": 0,
- "initial_notes": "string",
- "final_notes": "string",
- "creation_time": "2019-08-24T14:15:22Z",
- "creation_user": 0,
- "mod_time": "2019-08-24T14:15:22Z",
- "mod_user": 0
}
}
]
}What it does: Returns the list of programs that this record could be referred to next - it is a candidate list for making a NEW referral, not a log of past referrals. The list excludes any program the record is already linked to, and is restricted to programs whose "referrals" setting allows receiving referrals.
When to use it:
What you'll need:
What you'll get back:
A collection of bare program objects (id and name only) for the eligible programs.
Results can be paginated, sorted, and filtered with the page, sort, and filter
query parameters.
| id required | integer <int32> |
| key | string |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
| Authorization required | string Header that carries token for request Authorization |
Array of objects (ApricotProgram) |
curl -X GET "https://api.bonterra.network/v1/apricot/records/12345/referrals/programs?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "type": "programs",
- "id": 1,
- "attributes": {
- "name": "Sample Program"
}
}
]
}What it does: Retrieves the audit log / activity history of actions that have already been performed on records, such as when a record was Viewed, Created, Modified, Deleted, or Archived by Merge. Each entry is a historical audit event, not a configurable workflow action type - there is no concept of "available actions" or per-action permissions in this API.
When to use it:
What you'll need:
page[size] is required); sort/filter are optional, to narrow down resultsWhat you'll get back: Array of record action (audit log) entries, each containing:
action field for the full set of real values)required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order |
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecordAction) |
curl -X GET "https://api.bonterra.network/v1/apricot/records/actions?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 25,
- "currentPage": 1,
- "numPages": 4,
- "sortBy": "creation_time",
- "sortAsc": true
}, - "data": [
- {
- "id": 98765,
- "type": "records",
- "attributes": {
- "document_id": 12345,
- "form_id": 100,
- "row_id": 4,
- "tier_1": 0,
- "action": "Record Modified",
- "record_name": "John Doe",
- "form_name": "Client Intake",
- "creation_user_name": "Jane Smith",
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-10-15T14:30:00Z",
- "mod_user": 1487
}, - "links": {
- "self": "/apricot/records/actions/98765"
}
}
]
}What it does:
Search for records using a text query, optionally scoped to specific fields. This GET
endpoint and POST /apricot/records/search call the same underlying search service and
are functionally identical - this endpoint just accepts its parameters as query string
parameters instead of a JSON body.
When to use it:
What you'll need:
What you'll get back: Array of matching records with pagination metadata, similar to GET /records
Search Options:
form_id (required)
search (required)
fieldIdsToMatch (optional)
fieldIdsToMatch=1001&fieldIdsToMatch=1002)filter (optional)
filter[key]=value syntax as other
list endpointsfilter[id]=123 matches a specific record IDfilter[name]=Client matches against the form's designated record-name fieldfilter[field_<id>]=value matches against any other specific fieldpage (required)
page[size] is required and must be between 1 and 100; paginates search resultsImportant notes:
form_id and search are both required; omitting either returns a 400form_id that doesn't resolve to an existing form returns a 404search string tokenizes to nothing and returns
zero records - it does NOT return all records in the formdisableFuzzy, disablePrefix, disableWildcard, or wildcardPlacement
option - this API does not expose configurable fuzzy/prefix/wildcard search behavior| form_id required | integer <int32> Example: The ID of the form to query records from |
| search required | string Example: Search query string to match against record fields |
| fieldIdsToMatch | Array of integers Example: fieldIdsToMatch=1001&fieldIdsToMatch=1002 Limit the search to specific field IDs, passed as repeated query params (e.g.
|
object Example: filter[active]=1 Filter parameters to narrow down results. Use field names as keys | |
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
curl -X GET "https://api.bonterra.network/v1/apricot/records/search?form_id=2&search=John%20Doe&page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does:
Search for records using a text query, optionally scoped to specific fields. This POST
endpoint and GET /apricot/records/search call the same underlying search service and
are functionally identical - this endpoint just accepts its parameters as a JSON body
instead of query string parameters.
When to use it:
What you'll need:
What you'll get back: Array of matching records with pagination metadata, similar to GET /records
Search Options:
form_id (required)
search (required)
fieldIdsToMatch (optional)
filter (optional)
filter[key]=value syntax as other
list endpointsfilter: {id: 123} matches a specific record IDfilter: {name: "Client"} matches against the form's designated record-name fieldfilter: {field_<id>: value} matches against any other specific fieldpage (required)
page.size is required and must be between 1 and 100; paginates search resultsImportant notes:
form_id and search are both required; omitting either returns a 400form_id that doesn't resolve to an existing form returns a 404search string tokenizes to nothing and returns
zero records - it does NOT return all records in the formdisableFuzzy, disablePrefix, disableWildcard, or wildcardPlacement
option - this API does not expose configurable fuzzy/prefix/wildcard search behavior| Authorization required | string Header that carries token for request Authorization |
Search query
Required: form_id, search, and page (page.size) Optional: fieldIdsToMatch, to scope the search to specific fields; filter, to narrow results further
| form_id required | integer <int32> ID of the form to search records in |
| search required | string Search query string to match against record fields |
| fieldIdsToMatch | Array of integers Limit search to specific field IDs (if empty, searches all fields) |
object Narrows search results further. | |
required | object Paginates search results. |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
{- "form_id": 2,
- "search": "John Doe",
- "page": {
- "number": 1,
- "size": 20
}
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}What it does: Retrieves a specific subset of records for a form, scoped to a caller-supplied list of record (document) IDs plus the desired field set. This lets you retrieve multiple specific records in a single request without having to make individual GET requests.
When to use it:
What you'll need:
What you'll get back: Collection of complete record objects matching the provided IDs, including:
Performance tip: This is more efficient than making individual GET requests for each record when you need to fetch multiple specific records at once.
| Authorization required | string Header that carries token for request Authorization |
Form ID, desired fields, and array of record IDs to retrieve
| form_id required | integer <int32> The tier 1 form id to query against |
| desired_fields required | Array of strings The fields that will be included in the result. For active queries, this should contain name and email fields, minimum. For archived queries, this set is ignored. |
| included_records required | Array of integers <int32> [ items <int32 > ] The document ids that should be included in the response |
| searching | string If present, the desired_fields array will have sql like applied to each field with this string (active queries only) |
object or null Optional filters to narrow the queried records | |
object Pagination for the results | |
object Sort order for the results | |
| pagination | boolean Whether the results should be paginated |
| condensed_record_query | boolean Default: false If true, skips mapping the raw query results into fully-formed record objects |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects | |
object Envelope-level hypermedia links (in addition to the meta block) |
{- "form_id": 2,
- "desired_fields": [
- "field_2_first",
- "field_2_last"
], - "included_records": [
- 12345,
- 12346,
- 12347,
- 12350
]
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
], - "links": {
- "related": [
- {
- "href": "string"
}
]
}
}What it does: Retrieves records for participants who have not yet registered for the client portal. This is used to manage portal invitations and track which clients need portal access setup.
When to use it:
What you'll need:
What you'll get back: Records for participants without portal registration.
| Authorization required | string Header that carries token for request Authorization |
| form_id required | integer <int32> The tier 1 form id to query against |
| desired_fields required | Array of strings The fields that will be included in the result. Must contain name (i.e. field_123_first, field_123_last) and email fields, minimum |
| exclusions | Array of integers <int32> [ items <int32 > ] The document ids to exclude from the result; these have already been registered in Portal |
| last_mod_date | string or null If present, only retrieve data records with a mod_time greater than or equal to this 'YYYY-MM-DD' value |
| searching | string or null If present, the desired_fields array will have sql like applied to each field with this string |
required | object Pagination for the results. Required - requests without both page_size and page_num will fail. |
required | object Sort order for the results. Required - requests without both sort_col and sort_asc will fail. |
object or null Optional filters to narrow the queried records. Use filtering.program to scope by program (there is no top-level program_id field) | |
| paginatedResult | boolean Whether the results should be paginated |
| condensed_record_query | boolean Default: false If true, skips mapping the raw query results into fully-formed record objects |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotRecord) Array of record objects |
{- "form_id": 0,
- "desired_fields": [
- "string"
], - "exclusions": [
- 0
], - "last_mod_date": "string",
- "searching": "string",
- "paging": {
- "page_size": 0,
- "page_num": 0
}, - "sorting": {
- "sort_col": "string",
- "sort_asc": true
}, - "filtering": {
- "site": 0,
- "program": 0
}, - "paginatedResult": true,
- "condensed_record_query": false
}{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 12345,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-15T14:30:00Z",
- "creation_user": 1487,
- "mod_time": "2023-11-18T09:15:00Z",
- "mod_user": 1487,
- "field_1001": "John Doe",
- "field_1002": "john.doe@example.com",
- "field_1003": "2023-10-15"
}, - "links": {
- "self": "/apricot/records/12345"
}
}, - {
- "id": 12346,
- "type": "records",
- "attributes": {
- "form_id": 100,
- "parent_id": null,
- "creation_time": "2023-10-16T10:00:00Z",
- "creation_user": 1488,
- "mod_time": "2023-11-17T15:30:00Z",
- "mod_user": 1488,
- "field_1001": "Jane Smith",
- "field_1002": "jane.smith@example.com",
- "field_1003": "2023-10-16"
}, - "links": {
- "self": "/apricot/records/12346"
}
}
]
}Retrieves a list of all forms available in your Apricot instance. Forms are the templates used to collect data in records.
Common use cases:
Response includes:
required | object Example: page[number]=1&page[size]=20 Pagination parameters for the result set. Always pass at least |
| sort | string Examples:
Sort order for results. Prefix with '-' for descending order. Defaults to |
object Example: filter[active]=1 Filter parameters to narrow down results. For this endpoint, only | |
| include | string Example: include=all Comma-separated list of related data to include in each form's attributes. Supported values are |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
object (ApricotLinks) Hypermedia links for navigation and resource discovery | |
Array of objects (ApricotShallowForm) |
curl -X GET "https://api.bonterra.network/v1/apricot/forms?page[size]=20" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 25,
- "currentPage": 1,
- "numPages": 4,
- "sortBy": "creation_time",
- "sortAsc": true
}, - "links": {
- "self": "/apricot/records/12345",
- "first": "/apricot/records?form_id=100&page=1",
- "prev": "/apricot/records?form_id=100&page=1",
- "next": "/apricot/records?form_id=100&page=3",
- "last": "/apricot/records?form_id=100&page=10"
}, - "data": [
- {
- "id": 100,
- "type": "forms",
- "attributes": {
- "name": "Client Intake Form",
- "parent_id": null,
- "description": "Form for collecting client information during intake",
- "active": 1,
- "creation_time": "2022-01-15T10:00:00Z",
- "creation_user": "admin@example.com",
- "mod_time": "2023-11-01T14:30:00Z",
- "mod_user": "admin@example.com",
- "sort_order": 1,
- "reference_tag": "INTAKE_V2",
- "program_assignment_type": 1,
- "form_logic_enabled": 1,
- "guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
- "parent_guid": null
}
}
]
}What it does: Retrieves detailed information about a specific form, including its complete structure, sections, field definitions, field types, and all field IDs. This is essential for working with records and attachments.
When to use it:
What you'll need:
What you'll get back: Complete form structure including:
CRITICAL: Finding Attachment Field IDs
This endpoint is essential for discovering which field IDs are attachment fields.
Steps to find attachment field IDs:
sections arrayfields arrayfield_type_id indicates an attachment fieldid value - this is what you use for attachmentsExample: If you find a field with id: 827 and it's an attachment type:
field_827 when creating records with attachments (multipart/form-data)/records/{record_id}/attachment/827 for the attachment endpointField Type Reference: Common field_type_id values:
Important notes:
sections.fields array shows fields in display orderrequired | integer or string Form ID. If the value is not numeric, it is looked up as the form's |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
object (ApricotLinks) Hypermedia links for navigation and resource discovery | |
Array of objects (ApricotForm) Array of form objects |
curl -X GET "https://api.bonterra.network/v1/apricot/forms/2" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 2
}, - "data": [
- {
- "id": 100,
- "type": "forms",
- "attributes": {
- "name": "Client Intake Form",
- "active": 1,
- "description": "Form for collecting client information",
- "guid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}, - "links": {
- "self": "/apricot/forms/100"
}
}, - {
- "id": 101,
- "type": "forms",
- "attributes": {
- "name": "Follow-up Assessment",
- "active": 1,
- "description": "Follow-up assessment form",
- "guid": "b2c3d4e5-f6a7-8901-bcde-f12345678901"
}, - "links": {
- "self": "/apricot/forms/101"
}
}
]
}What it does: Retrieves a complete list of all fields within a specific form. This is the most efficient way to get just the field definitions without the full form structure.
When to use it:
What you'll need:
What you'll get back: Array of field objects containing:
Note: This endpoint returns fields only. For complete form structure including sections and metadata, use GET /apricot/forms/{id} instead.
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
object (ApricotMeta) Metadata about the response, including pagination information | |
Array of objects (ApricotFormField) |
curl -X GET "https://api.bonterra.network/v1/apricot/forms/2/fields" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "meta": {
- "count": 25,
- "currentPage": 1,
- "numPages": 4,
- "sortBy": "creation_time",
- "sortAsc": true
}, - "data": [
- {
- "id": 1001,
- "section_id": 50,
- "field_type_id": 1,
- "sort_order": 1,
- "label": "Full Name",
- "is_required": 1,
- "active": 1,
- "is_searchable": 1,
- "is_duplicate": 0,
- "is_hidden": 0,
- "is_readonly": 0,
- "tooltip": "Enter the client's full legal name",
- "guid": "field-a1b2c3d4-e5f6-7890",
- "reference_tag": "CLIENT_NAME",
- "field_properties": [ ],
- "field_options": [ ]
}
]
}What it does: Retrieves the programs that have access to a specific form, filtered to the programs the authenticated caller has access to (unless the caller is an admin). A caller with no accessible programs receives an empty array, even if the form is actually linked to programs. In Apricot, forms can be shared across multiple programs, allowing different service areas to use the same data collection structure.
When to use it:
What you'll need:
What you'll get back: Array of program objects that have access to this form and that you (the caller) can access, each containing:
Common scenarios:
Use this to:
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
Array of objects (ApricotProgram) Array of program objects |
curl -X GET "https://api.bonterra.network/v1/apricot/forms/2/programs" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}What it does: Retrieves the list of programs that the authenticated user has access to for a specific form. This helps determine which programs a user can create or view records in for the given form.
When to use it:
What you'll need:
What you'll get back: Array of programs the authenticated user can access for this form.
| id required | integer <int32> |
| Authorization required | string Header that carries token for request Authorization |
Array of objects (ApricotProgram) Array of program objects |
curl -X GET "https://api.bonterra.network/v1/apricot/forms/2/userPrograms" \ -H "Authorization: Bearer YOUR_ACCESS_TOKEN"
{- "data": [
- {
- "id": 200,
- "type": "programs",
- "attributes": {
- "name": "Youth Services",
- "description": "Program for youth development and support",
- "active": 1,
- "site_id": 1,
- "sort_order": 1
}, - "links": {
- "self": "/apricot/programs/200"
}
}, - {
- "id": 201,
- "type": "programs",
- "attributes": {
- "name": "Family Support",
- "description": "Family counseling and support services",
- "active": 1,
- "site_id": 1,
- "sort_order": 2
}, - "links": {
- "self": "/apricot/programs/201"
}
}
]
}