rather than completed Developers - Four/Four

Developers

Got questions? Need a demo? We are here to help.

Getting started

#

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.

OAuth Authentication

#

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.

Adding an API client

You must add an API client in Four/Four to generate OAuth credentials for your application.

To add a client

  1. Sign in as an admin into your Four/Four instance. Go to the connections page , then scroll down to "OAuth Clients".
  2. Click Create Client.
  3. Complete the following fields:
    • Client name - The name of your client. This name will be visible to users when they are prompted to grant access to your application.
    • Redirect URLs - Enter the URL or URLs that Four/Four should use to redirect users after they decide whether to authorize your application to access Four/Four. The URL must be absolute, not relative, and should use HTTPS unless you are using localhost.
  4. Click Create.
  5. 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.

  6. Save the client secret somewhere safe.

Use the client id (also known as the unique identifier) and the client secret in your application as described in this following section.

Implementing an OAuth Authorization Flow

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:

  • Step 1 - Send the user to the Four/Four authorization page
  • Step 2 - Handle the user's authorization decision
  • Step 3 - Get an access token from Four/Four
  • Step 4 - Use the access token in API calls

Step 1 - Send the user to the Four/Four authorization page

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):

  • response_type - Required. Four/Four returns an authorization code in the response, so specify code as the response type. Example: response_type=code .
  • redirect_uri - Required. The URL that Four/Four should use to redirect users after they decide whether to authorize your application to access Four/Four. The URL must be absolute, not relative, and should use HTTPS unless you are using localhost. This URL should be one of the URLs you provided during client registration.
  • client_id - Required. The unique identifier you obtained when you registered your application with Four/Four. See the section above.
  • state - An arbitrary string included in the response from Four/Four after the user decides whether to grant access. You can use the parameter to guard against cross-site request forgery (CSRF) attacks. In a CSRF attack, the end-user is tricked into clicking a link that performs an action in a web application where the end-user is still authenticated. To guard against this kind of attack, add some value to the state parameter and validate it when it comes back.

Step 2 - Handle the user's authorization decision

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.

Step 3 - Get an access token from 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:

  • grant_type - Specify authorization_code as the value.
  • code - Use the authorization code you received from Four/Four after the user granted access.
  • client_id - Use the unique identifier you received when you registered your application with Four/Four.
  • client_secret - Use the secret value you received when you registered your application with Four/Four.
  • redirect_uri - The URL of the resource that Four/Four should send the access token. It again should be one of the URLs you specified during client registration.

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
}

Step 4 - Use the access token in API calls

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..."

Step 5 - Refresh your access token

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

Making API requests

#

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.

Fetching information about your session

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.

Fetching entity sets

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/Conversations
This will return a JSON response containing an array of conversation entities.

Retrieving single entities by ID

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`.

Handling pagination

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.

Custom CRM Importer

#

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

Authentication

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.

Standard and additional fields

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.

Data type encoding

The following rules should be followed to map data types into CSV:

  • Fields declared in the header but missing in the record are stored as null values (ie, when updating a record, send all field values your header declares)
  • Dates and timestamps should be provided in ISO 8601 format in the UTC timezone
  • Booleans should be provided as the literal strings 'true' or 'false' (lowercase)
  • 'currency' fields should use ISO 4217 currency codes

Submitting records

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.

Checking import status

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.

Reading back a single record

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 .

Deleting records

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.

Webhooks

#

Four/Four supports notifying your service of changes via signed, HTTP POST webhooks.

Set Up Your Webhook Endpoint

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

Configure the webhook in Four/Four

  1. Sign in as an admin into your Four/Four instance. Go to the connections page , then scroll down to "Webhooks".
  2. Click Add Webhook.
  3. Complete the following fields:
    • Endpoint - The HTTP endpoint that will receive the POST requests.
    • Events - The types of event you want your webhook to receive.
    • Linked OAuth client - (Optional) The OAuth client this webhook is linked to. When a webhook is linked to a client, it will receive notifications for all Four/Four tenants that have authorized your application for API access. With no linked client the webhook will only receive events for the tenant it was created in.
  4. Click Create.

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.

Listen for Incoming Requests

Set up a route or controller action on your server to listen for POST requests on the webhook endpoint.

Parse the Request

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.

Validate the Webhook Signature

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.

Respond to the Webhook

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.

Services

#

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

Model Context Protocol (MCP)

#

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.

Connecting to the MCP server

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.