rather than completed
You can try out the Four/Four platform with a free trial account. If you're interested in becoming a Four/Four developer partner, we can convert your trial account into a sponsored account.
Full API schema information including all endpoints is available in the generated documentation.
You must use OAuth2 to authenticate all your API requests to Four/Four. OAuth provides a secure way for your application to access account data without requiring sensitive information such as usernames and passwords be sent with the requests. To use OAuth authentication, you need to register your application with Four/Four by adding an API client. You also need to add some functionality to your application to implement an OAuth authorization flow.
You can use the OAuth client to authenticate access to your instance, and it can be used by other Four/Four customers to allow your service to access their Four/Four instance.
You must add an API client in Four/Four to generate OAuth credentials for your application.
Upon successful creation, the client id and client secret will be displayed. Take note of these values as you'll need both to create an OAuth access token later.
Use the client id (also known as the unique identifier) and the client secret in your application as described in this following section.
Four/Four supports the authorization code grant flow, which produces an authorization code after the user grants your app access to their account. Your app can then exchange the authorization code for an access token to use in API requests. Refresh tokens are also issued for the authorization code grant flow.
To implement the authorization code grant flow, you need to add the following functionality to your application:
First, your application must send the user to the Four/Four authorization page. The page asks the user to authorize your application to access Four/Four as if it was them. After the user makes a choice, Four/Four sends the choice and a few other bits of information back to your application.
To send the user to the Four/Four authorization page add a link or button in your application that sends the user to the following URL:
https://fourfour.ai/oauth/authorize
The request should be GET, with the following parameters (make sure to URL-encode the parameters):
Your application must handle the response from Four/Four indicating the user's decision. When the user authorizes the application, the authorization code will be found in the redirected URL parameters, for example:
{redirect_uri}?code=7xqwtlf3rrdj8uyeb1yf
The authorization code is valid only for a short time.
If the user decides to deny the application, the URL will contain an error parameter.
{redirect_uri}?error=access_denied
Use these values to control the flow of your application. If the URL contains a code parameter, get an access token from Four/Four as described in the following section. This access token is used to make API calls to Four/Four.
If your application received an authorization code from Four/Four in response to the user granting access, your application can call Four/Four to get an access token. To get the access token, make a POST request to the following endpoint:
https://fourfour.ai/oauth/token
Include the following required parameters in the request:
The request must be over HTTPS and the parameters must be URL-encoded.
curl https://fourfour.ai/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=authorization_code&code={your_code}&client_id={your_client_id}&client_secret={your_client_secret}&redirect_uri={your_redirect_uri}' \
-X POST
Example response
HTTP/1.1 200 OK
Content-Type: application/json
{
"access_token": "gErypPlm4dOVgGRvA1ZzMH5MQ3nLo8bo...",
"refresh_token": "x4AoIVTmaoZmpl25ZX6vTPL2f0aZXHbn...",
"token_type": "Bearer",
"expires_in": 86400
}
The access token is required to make API calls. Set the token in the request's authorization header as follows:
Authorization: Bearer {a_valid_access_token}
For example, a curl request to show your account details would look as follows:
curl https://fourfour.ai/odata/me \
-H "Authorization: Bearer gErypPlm4dOVgGRvA1ZzMH5MQ3nLo8bo..."
When the access token expires, your API requests will receive a 401 Unauthorized response. To use the refresh token, make a POST request to the service’s token endpoint with grant_type=refresh_token , and include the refresh token, client_id and client_secret.
curl https://fourfour.ai/oauth/token \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=refresh_token&refresh_token={your_refresh_token}&client_id={your_client_id}&client_secret={your_client_secret}' \
-X POST
The Four/Four REST API uses the OData protocol. OData (Open Data Protocol) is a standardized protocol used to query and manipulate data using RESTful APIs. It was developed to simplify the process of building APIs and to provide a uniform way to expose and access data. OData version 4.01, the latest iteration of the protocol, offers a robust framework for building scalable and efficient data services. This introduction will guide you through the basics of making OData 4.01 requests, covering essential operations such as fetching entity sets, retrieving individual entities by their identifiers, and handling pagination in data queries.
You can retrieve information about the user and tenant that authorized your application for the provided bearer token.
GET /odata/me
An example payload is as follows:
{
"@context": "https://fourfour.ai/odata/$metadata#me",
"user_id": "9e0744e1-8410-4bcb-a51c-4225e7d0e72a",
"user_name": "Chris Lloyd",
"user_email": "chris@fourfour.ai",
"tenant_id": "44c8c2c0-5627-4761-80b7-10a089d1b7bb",
"tenant_name": "SuperCo"
}
The payload includes the tenant_id which is needed when identifying webhooks received from other customer accounts. Note that the user_id s unique to the user identity, but not unique to the tenant - a single user can be a member of multiple tenants. The access token received can only be used to access on behalf of this user, only on the tenant indicated in the response.
An entity set in OData represents a collection of entities of a particular type, similar to a table in a relational database. To retrieve an entire entity set, you can send a simple HTTP GET request to the relevant endpoint. For example, to fetch a list of conversations, you would perform the following request:
GET /odata/ConversationsThis will return a JSON response containing an array of conversation entities.
Fetching a specific entity within an entity set requires specifying the unique identifier (ID) of that entity in the URL. This is akin to retrieving a single record from a database table based on its primary key. For instance, to get a conversation with an ID of `5a160c5c-e861-11ef-9289-3b02e438cdf3`, the request would be:
GET /odata/Conversations/5a160c5c-e861-11ef-9289-3b02e438cdf3
This query will return the JSON representation of the conversation with ID `5a160c5c-e861-11ef-9289-3b02e438cdf3`.
When dealing with substantial amounts of data, enabling pagination can optimize data retrieval performance. OData supports pagination through the `$top` and `$skip` query options, allowing you to control the number of entries returned and to skip over a defined number of results. For example, if you want to retrieve the first 10 conversations, use:
GET /odata/Conversations?$top=10
To fetch the next 10 conversations, skip the first 10 entries and fetch subsequent ones:
GET /odata/Conversations?$top=10&$skip=10
OData responses will include a @odata.nextLink attribute, providing a URI to retrieve subsequent pages, ensuring seamless navigation through paginated data.
To review all the available endpoints and query parameters, check out the full documentation.
If you have a custom CRM that Four/Four does not support then the CRM importer lets you bulk import your own records so they can be matched against conversations and surfaced throughout the platform. You submit records as CSV, one record per row, and Four/Four creates or updates them as needed. It is recommended that you first push all records, and then deltas periodically as the content changes. The importer supports the following record types, but you do not have to use them all:
| Record type | Type identifier |
|---|---|
| Account | account |
| Contact | contact |
| Opportunity | opportunity |
| Lead | lead |
| User | user |
The CRM Importer is authenticated with a bearer token issued by Four/Four. Navigate to connections and create a Personal Access Token with the Import data scope. Once you have it, send it in the Authorization header on every request:
Authorization: Bearer {your_token}
Requests with a missing or invalid token receive a 401 Unauthorized response.
Each record type has a set of standard fields that map directly onto the corresponding fields in a Four/Four CRM record. The first column of every CSV must be id , which is your own unique identifier for the record and is used to create, update, and delete it. The standard fields available for each record type are listed in the generated API documentation.
Any column in your CSV that is not a standard field is stored as an additional field. Additional fields let you attach your own custom data to a record without it needing to map onto a standard Four/Four field. They are preserved exactly as submitted and returned alongside the standard fields when you read a record back. There is no need to declare additional fields in advance, simply include the columns you want. Additional fields can be configured as custom filters in Four/Four.
The following rules should be followed to map data types into CSV:
To create or update records, send an HTTP PUT request to the import endpoint for the record type, with the CSV as the raw request body. The first row is the header containing your column names, and each subsequent row is a record. Records are matched on the id column: an unrecognised id creates a new record, while an existing one updates it.
There is no hard limit on the number of records in a single request, but your client must keep the connection open until the upload completes and Four/Four returns the 202 Accepted response. If your client disconnects before then, the upload is incomplete and the import is not queued. Once accepted, the records are processed in the background regardless of your connection. We recommend importing around 10,000 records at a time to keep uploads and individual import jobs manageable.
In the example below, name , website , and industry are standard account fields, while crm_segment is an additional field:
curl https://fourfour.ai/import/crm/account \
-X PUT \
-H "Authorization: Bearer {your_token}" \
-H "Content-Type: text/csv" \
--data-binary $'id,name,website,industry,crm_segment\nacc-001,Acme Industries,https://acme.test,Robotics,Enterprise\nacc-002,TechCorp,https://techcorp.test,Software,Mid-Market'
A successful submission returns 202 Accepted with a JSON body containing the job id, and a Location header pointing to the status endpoint for that job. Records are validated and processed asynchronously, so the response confirms the import was accepted.
HTTP/1.1 202 Accepted
Content-Type: application/json
Location: https://fourfour.ai/import/job/9e259d7a-8dd2-42ce-beb8-ef637eda7ef7
{
"job": "9e259d7a-8dd2-42ce-beb8-ef637eda7ef7"
}
Use the job id to poll the status endpoint for progress and to discover any problems with the CSV.
Because records are processed asynchronously, both submitting and deleting return a job id. Send an HTTP GET request to the job endpoint, using the Location header returned with the 202 Accepted response to track progress and confirm completion.
curl https://fourfour.ai/import/job/9e259d7a-8dd2-42ce-beb8-ef637eda7ef7 \
-H "Authorization: Bearer {your_token}"
Example response:
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "completed",
"processed": 2,
"error": null,
"error_line": null,
"created_at": "2025-02-06T14:41:38+00:00",
"updated_at": "2025-02-06T14:41:40+00:00",
"started_at": "2025-02-06T14:41:39+00:00",
"completed_at": "2025-02-06T14:41:40+00:00"
}
The status field is one of pending , processing , completed , or failed , and processed is the number of records handled so far. If the CSV could not be processed the status is failed , error describes the problem, and error_line indicates the offending row where applicable.
To check what Four/Four has stored for a record, useful when testing your submissions, send an HTTP GET request to the endpoint for the record type, with your record id appended to the path. The response is a CSV containing a header row and a single data row, with both standard and additional fields merged together.
curl https://fourfour.ai/import/crm/account/acc-001 \
-H "Authorization: Bearer {your_token}"
Example response:
HTTP/1.1 200 OK Content-Type: text/csv id,name,website,industry,crm_segment acc-001,Acme Industries,https://acme.test,Robotics,Enterprise
If no record exists for that id , the endpoint returns 404 Not Found .
To delete records, send an HTTP DELETE request to the endpoint for the record type. The body is a CSV that only needs an id column; any other columns are ignored. Each row identifies a record to delete.
curl https://fourfour.ai/import/crm/account \
-X DELETE \
-H "Authorization: Bearer {your_token}" \
-H "Content-Type: text/csv" \
--data-binary $'id\nacc-001\nacc-002'
As with submitting, a successful request returns 202 Accepted with a job id you can poll for status. Only records that you imported are affected; records that originated from other connected services are left untouched.
Four/Four supports notifying your service of changes via signed, HTTP POST webhooks.
Set up a URL on your server where the webhook provider will send HTTP POST requests. This URL will act as your webhook endpoint. For example, https://yourdomain.com/webhook
Upon successful creation, the webhook secret will be displayed. Take note of this value as you'll need it to validate the authenticity of the webhook messages you receive.
Set up a route or controller action on your server to listen for POST requests on the webhook endpoint.
When a request is received, parse the payload, which comes in JSON format. Ensure you handle it correctly to avoid errors related to incorrect data types or format issues.
An example payload is as follows:
{
"timestamp": "2025-02-06T14:41:38+00:00",
"event": "conversation_processing_complete",
"tenant": "9e1f42e6-dda6-46c6-9740-f51fac539cf8",
"payload": {
"id": "9e259d7a-8dd2-42ce-beb8-ef637eda7ef7"
}
}
The payload contains the timestamp, the event being described, the ID of the tenant that the event originated from and the payload. The payload is event-specific, in this case the ID refers to the conversation ID that has finished processing.
The webhook request will include a signature header named Signature which contains the HMAC signature of the payload to verify its authenticity.
Use the SHA-256 hashing algorithm provided by your platform and compute a hash of the payload using the secret key provided earlier. This is generally done as follows:
HMAC_SHA256(SECRET_KEY, JSON_PAYLOAD)
Compare your computed signature with the signature from the webhook header. If the signatures match, proceed to process the payload. - If they do not match, discard the request and optionally log an error or alert for further investigation.
Send an appropriate HTTP response status to acknowledge receipt of the webhook. Typically, a 200 OK status code if everything is successful or 40x/50x if there's an error. If we receive an error status we will retry sending the webhook up to three times using an exponential backoff algorithm.
Four/Four integrates and aggregates many conversation sources. In entity sets such as Conversations the API presents a service to identify the originating service and service_id as the ID that service used to identify it internally.
The list of service identifiers Four/Four uses is:
| Service | Identifier |
|---|---|
| 3CX | 4d2c8aae-0e1f-4f44-9c7c-2b1f7a3d4ee6 |
| Aircall | 4b5ad3f0-acde-11ef-b2fd-fb8bbf6b0760 |
| Attention | 8d2f5e10-8a1a-4f6b-b3c1-1cdb27a47e93 |
| Attio | 3b8f2c10-1607-11f1-a2d4-8b3e9c7f5a21 |
| Avoma | 85307a92-2067-11f0-8f61-2b404342a9a1 |
| Chorus | 2d29be9e-a8f3-11ef-98ee-071763940244 |
| Clari | c5990584-582c-11f0-aff2-e35b634f5d88 |
| Craft.io | 2c6bdfbd-85dd-4ac8-afd0-4f93effa7fb7 |
| Dovetail | 9d742b80-1834-11ef-9d63-37de81059583 |
| Dynamics 365 | a8c7e1f0-a9a3-11f0-972a-cf2d40de4700 |
| Fireflies | a4535e3e-2b35-11f0-b47d-070e8f0f4ba8 |
| Four/Four Notetaker | 9a6a9d3a-ff29-11ee-bf05-e3647beb6dd1 |
| Gong | 2ced8f92-354e-11ee-8b1e-6f08dcfc80c2 |
| Google Calendar | d8dffa84-11e8-11ef-9459-f75cbaa47af3 |
| Google Mail | 650383d0-c6e4-11f0-bd4c-6b8dd6eff051 |
| Google Meet | 255cab90-5ae8-11ee-8ed5-0fe58e1eacd7 |
| HubSpot | 2a587d15-0bb5-49bd-86e4-67730b94c3f7 |
| Intercom | f65905b6-b7c8-11ef-9ae0-476e68765d45 |
| Jiminny | e3b03a44-83c3-11ef-8ba1-c7ed1de301db |
| Jira | 1fb75b16-7534-435c-9bfb-58452232cd76 |
| Manual Upload | 66f8a52a-1908-11ef-a0d6-475211cce46c |
| Marketo | 5a67a228-44a4-4826-aebb-db554d5448cf |
| Microsoft Teams | 196a746a-0f3b-4bec-b33c-70147ac53961 |
| NiCE CXone | b2bcea10-4ba1-11f1-b2b7-f0190254f384 |
| Notion | 4a4b4a37-1f30-4ef7-a5cf-bf3d18af9186 |
| Outlook Calendar | d55968dc-fefb-11ee-b004-6b1c6108891d |
| Outlook Mail | 47b6429a-f876-11f0-a6c8-cbf1683dbd2d |
| Outreach | fbd68c58-92f6-11ef-a8ee-cbb9775642bb |
| Planhat | 27a9c86c-1f7f-11f0-8874-b708ff163df8 |
| ProductBoard | 0e66679e-594a-11ef-a2b0-bfcbc852de8e |
| Pylon | 73191d08-d676-11f0-bbc3-66539a87c87a |
| RingCentral | 261de476-f236-11f0-88e3-cf91d1e58952 |
| Salesforce | b9d1c5a8-bd2d-45bb-b394-bb6c70bee099 |
| Salesloft | c175af54-4f03-4d48-8ee6-da8cd6837eb4 |
| ServiceNow | 13a48542-3ddc-11f1-9583-66539a87c879 |
| Slack | e25731da-68a0-11f0-a8cb-a3d84b86fcc8 |
| Weflow | 590fe43a-3416-471e-8d7e-720b92348c44 |
| Zendesk | eb778e68-ab0e-11ef-b5a1-672f26fa0665 |
| Zoom | 98bb866e-44f5-4e5e-8a6d-e4610b2d6a03 |
Four/Four exposes a native MCP server, allowing AI agents like Claude, ChatGPT, and custom LLM applications to query your customer intelligence directly. The MCP server provides structured tools for searching conversations, insights, accounts, and contacts - grounding AI workflows in real customer data without building custom integrations.
The MCP server url is https://fourfour.ai/mcp
Authentication is automatic via OAuth discovery.
We use cookies as specified in our Privacy Policy. You agree to consent to the use of these technologies by clicking Allow Cookies.