Skip to main content

Bulk import notes on deals

Updated over a week ago

This guide explains how to add notes to existing deals in bulk using the Folk API. The process involves retrieving deal information first, then creating notes for each deal.

Overview

The bulk update process consists of three main steps:

  1. Prepare your data - Organize deal information and notes in a CSV or Google Sheet

  2. Retrieve deal details - Use the GET Deal endpoint to fetch deal IDs

  3. Create notes in bulk - Loop through your data and create notes for each deal

Step 1: Prepare Your Data

Start with a CSV file or Google Sheet containing your deal information and notes. Your data should include:

  • Deal identifier (name, ID, or other unique identifier)

  • Note content

  • Author information (optional)

  • Additional metadata (optional)

Step 2: Retrieve Deal Information

For each deal in your data, you need to retrieve the deal ID using the GET List Deal endpoint. For example, you can use a filter to match the deal name with your CSV file or Google Sheet.

Endpoint

GET /v1/groups/{groupId}/{entityType}

Parameters

  • groupId (string, required): The ID of the group containing the deals

  • entityType (string, required): The deal entity type from your custom fields

Query Parameters

  • limit (integer, default: 20): The number of items to return (1-100)

  • cursor (string): For pagination across multiple pages. Don't include on first call

  • combinator (enum, default: "and"): Logical operator to combine filters ("and" or "or")

  • filter (object): Filters to apply using format : filter[attribute][operator]=value

Headers

Authorization: YOUR_API_KEY

Content-Type: application/json

Example Request

curl -X GET "https://api.folk.app/v1/groups/grp_abc123/deals" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json"

Response

The response will include deal information with the ID you need:

{
"data": {
"id": "obj_abc123def456ghi789jkl012mno345pqr678",
"name": "Acme Corporation Project",
"companies": [
{
"id": "com_987654321",
"name": "Acme Corp"
}
],
"people": [...],
"createdAt": "2021-01-01T00:00:00.000Z",
"customFieldValues": {
"Status": "Active",
"Deal value": "50000"
}
}
}

Important: Save the data.id value - this is what you'll use to create the note.

Step 3: Create Notes for Each Deal

Once you have the deal ID (which starts with "obj_"), use the Create Note endpoint to add notes to each deal.

Endpoint

POST /v1/notes

Headers

Authorization: YOUR_API_KEY

Content-Type: application/json

Request Body

{
"entity": {
"id": "obj_abc123def456ghi789jkl012mno345pqr678"
},
"visibility": "public",
"content": "Your note content here"
}

Parameters Explained

  • entity.id (required): The deal ID retrieved from Step 2

  • visibility (required): Either "public" (visible to all users) or "private" (visible only to you)

  • content (required): The note content (supports plain text and Markdown)

Example Request

curl -X POST "https://api.folk.app/v1/notes" \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"entity": {
"id": "obj_abc123def456ghi789jkl012mno345pqr678"
},
"visibility": "public",
"content": "Follow-up meeting scheduled for next week"
}'

Response

{
"data": {
"id": "nte_note123456789",
"entity": {
"id": "obj_abc123def456ghi789jkl012mno345pqr678",
"entityType": "deal",
"name": "Acme Corporation Project"
},
"content": "Follow-up meeting scheduled for next week",
"visibility": "public",
"author": {
"id": "usr_user123456789",
"fullName": "John Smith",
"email": "john.smith@example.com"
},
"createdAt": "2024-03-15T10:30:00.000Z"
}
}

Bulk Processing Implementation

To process multiple deals, implement a loop that processes each row of your CSV/Google Sheet:

Pseudocode Example

FOR each row in your CSV/Google Sheet:

1. Get deal identifier from row

2. Call GET List Deal endpoint with filter to retrieve deal ID

3. Extract the deal ID from response

4. Call POST Notes endpoint with:

- entity.id = extracted deal ID

- content = note content from row

- visibility = "public" or "private"

5. Call Google Sheet API to add “Done” each line you did (prevent duplicate)

6. Add delay between requests to respect rate limits

END FOR

Implementation

You can implement this process using automation tools like n8n, Zapier, or custom scripts. The key is to loop through your data and execute both API calls for each record.

Content Formatting

The note content supports Markdown formatting. You can include:

n8n Template available

(Copy paste directly in n8n)

{
"name": "Template FOLK NOTES API",
"nodes": [
{
"parameters": {},
"type": "n8n-nodes-base.manualTrigger",
"typeVersion": 1,
"position": [
240,
112
],
"id": "17c4c48a-acc8-4e47-99e5-efcb9ef91851",
"name": "When clicking ‘Execute workflow’"
},
{
"parameters": {
"options": {}
},
"type": "n8n-nodes-base.splitInBatches",
"typeVersion": 3,
"position": [
784,
112
],
"id": "06f2d96a-0f4d-4878-a716-03b47572d74b",
"name": "Loop Over Items"
},
{
"parameters": {
"amount": 1
},
"type": "n8n-nodes-base.wait",
"typeVersion": 1.1,
"position": [
992,
208
],
"id": "01844420-4ccd-41b4-859c-f224d2e795df",
"name": "Wait",
"webhookId": "338f9ba6-98d9-447a-84e4-04a304e59be6"
},
{
"parameters": {
"documentId": {
"__rl": true,
"value": "1_45SIjWxBaY_L94c2C2KtsnrDdnjdfugZ8BXCFbZnVw",
"mode": "list",
"cachedResultName": "EXPORT FOLK",
"cachedResultUrl": ""
},
"sheetName": {
"__rl": true,
"value": 862943313,
"mode": "list",
"cachedResultName": "final_export",
"cachedResultUrl": ""
},
"filtersUI": {
"values": [
{
"lookupColumn": "finish"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
496,
112
],
"id": "229d085f-c15b-45be-9763-502c75e58848",
"name": "GET ROW in CSV",
"credentials": {
"googleSheetsOAuth2Api": {
"id": "rpJwzTHsKNcKLYl4",
"name": "TESTACC"
}
}
},
{
"parameters": {
"url": "https://api.folk.app/v1/groups/grp_YOURGROUPID/Deals",
"sendQuery": true,
"queryParameters": {
"parameters": [
{
"name": "filter[name][eq]",
"value": "={{ $json.Deal }}"
},
{
"name": "limit",
"value": "1"
},
{
"name": "combinator",
"value": "and"
}
]
},
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_API_TOKEN"
}
]
},
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1232,
208
],
"id": "0c952b5f-793d-4fbc-9270-42357037882b",
"name": "GET - FOLK API1",
"alwaysOutputData": true
},
{
"parameters": {
"method": "POST",
"url": "https://api.folk.app/v1/notes",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "Bearer YOUR_API_TOKEN"
}
]
},
"sendBody": true,
"specifyBody": "json",
"jsonBody": "={\n \"entity\": {\n \"id\": \"{{ $json.data.items[0].id }}\"\n },\n \"visibility\": \"public\",\n \"content\": {{ JSON.stringify($('Wait').item.json.Content) }}\n}",
"options": {}
},
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1456,
208
],
"id": "689173ba-ea44-4e78-9558-5a895beb9e43",
"name": "CREATE NOTE - API FOLK1"
},
{
"parameters": {
"operation": "update",
"documentId": {
"__rl": true,
"value": "1_45SIjWxBaY_L94c2C2KtsnrDdnjdfugZ8BXCFbZnVw",
"mode": "list",
"cachedResultName": "EXPORT FOLK",
"cachedResultUrl": ""
},
"sheetName": {
"__rl": true,
"value": 862943313,
"mode": "list",
"cachedResultName": "final_export",
"cachedResultUrl": ""
},
"columns": {
"mappingMode": "defineBelow",
"value": {
"finish": "done",
"row_number": "={{ $('Wait').item.json.row_number }}"
},
"matchingColumns": [
"row_number"
],
"schema": [
{
"id": "Deal",
"displayName": "Deal",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "ID",
"displayName": "ID",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Parent ID",
"displayName": "Parent ID",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Author",
"displayName": "Author",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Author Date",
"displayName": "Author Date",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Content",
"displayName": "Content",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Attendees",
"displayName": "Attendees",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tagged Persons",
"displayName": "Tagged Persons",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tagged Organizations",
"displayName": "Tagged Organizations",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "Tagged Opportunities",
"displayName": "Tagged Opportunities",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "finish",
"displayName": "finish",
"required": false,
"defaultMatch": false,
"display": true,
"type": "string",
"canBeUsedToMatch": true
},
{
"id": "row_number",
"displayName": "row_number",
"required": false,
"defaultMatch": false,
"display": true,
"type": "number",
"canBeUsedToMatch": true,
"readOnly": true,
"removed": false
}
],
"attemptToConvertTypes": false,
"convertFieldsToString": false
},
"options": {}
},
"type": "n8n-nodes-base.googleSheets",
"typeVersion": 4.7,
"position": [
1664,
208
],
"id": "826c62fe-844f-4592-81fd-4d02a39672d1",
"name": "Update row in sheet",
"credentials": {
"googleSheetsOAuth2Api": {
"id": "rpJwzTHsKNcKLYl4",
"name": "TESTACC"
}
}
}
],
"pinData": {},
"connections": {
"When clicking ‘Execute workflow’": {
"main": [
[
{
"node": "GET ROW in CSV",
"type": "main",
"index": 0
}
]
]
},
"Loop Over Items": {
"main": [
[],
[
{
"node": "Wait",
"type": "main",
"index": 0
}
]
]
},
"Wait": {
"main": [
[
{
"node": "GET - FOLK API1",
"type": "main",
"index": 0
}
]
]
},
"GET ROW in CSV": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
},
"GET - FOLK API1": {
"main": [
[
{
"node": "CREATE NOTE - API FOLK1",
"type": "main",
"index": 0
}
]
]
},
"CREATE NOTE - API FOLK1": {
"main": [
[
{
"node": "Update row in sheet",
"type": "main",
"index": 0
}
]
]
},
"Update row in sheet": {
"main": [
[
{
"node": "Loop Over Items",
"type": "main",
"index": 0
}
]
]
}
},
"active": false,
"settings": {
"executionOrder": "v1"
},
"versionId": "0565c7a3-10cc-4103-b751-b50a97d46e5b",
"meta": {
"templateCredsSetupCompleted": true,
"instanceId": "0db6b51bd90b963ffe7af42e17939e58c6ce0afbea5705fb41d1f96b37a24265"
},
"id": "M8xtYD7PElsHqiDY",
"tags": []
}

Error Handling

Common errors and how to handle them:

  • 401 Unauthorized: Check your API key

  • 404 Not Found: Verify the deal ID exists

  • 400 Bad Request: Check your request format

  • 429 Too Many Requests: Implement rate limiting with delays

Rate Limiting

To avoid hitting rate limits:

  • Add delays between requests (100-200ms recommended)

  • Process in batches rather than all at once

  • Implement retry logic for failed requests

Best Practices

  1. Test with a small batch first before processing all your data

  2. Log all operations for debugging and verification

  3. Validate data before making API calls

  4. Handle errors gracefully and continue processing other items

  5. Keep backups of your original data

Did this answer your question?