OpenAPI Specification
openapi: 3.0.3
info:
title: Folk External Companies Webhooks API
description: Folk's public REST API lets you manage workspaces, groups, contacts, and real-time triggers.
version: '2025-06-09'
contact:
name: folk
email: tech@folk.app
url: https://folk.app
servers:
- url: https://api.folk.app
description: Folk's public API production base URL.
x-internal: false
tags:
- name: Webhooks
description: Operations related to webhooks.
paths:
/v1/webhooks:
get:
security:
- bearerApiKeyAuth: []
operationId: listWebhooks
summary: List webhooks
description: Retrieve a list of webhooks in the workspace.
tags:
- Webhooks
parameters:
- schema:
type: integer
minimum: 1
maximum: 100
default: 20
required: false
description: The number of items to return.
example: 20
name: limit
in: query
- schema:
type: string
maxLength: 128
required: false
description: A cursor for pagination across multiple pages of results. Don’t include this parameter on the first call. Use the `pagination.nextLink` value returned in a previous response to request subsequent results.
example: eyJvZmZzZXQiOjN9
name: cursor
in: query
responses:
'200':
description: A paginated list of webhooks in the workspace.
links:
updateWebhook:
operationId: updateWebhook
parameters:
companyId: $response.body#/data/items/0/id
description: The ids returned by the `GET /v1/webhooks` operation can be used as an input to the `PATCH /v1/webhooks/:webhookId` operation to update a webhook.
getWebhook:
operationId: getWebhook
parameters:
companyId: $response.body#/data/items/0/id
description: The ids returned by the `GET /v1/webhooks` operation can be used as an input to the `GET /v1/webhooks/:webhookId` operation to retrieve a webhook.
deleteWebhook:
operationId: deleteWebhook
parameters:
companyId: $response.body#/data/items/0/id
description: The ids returned by the `GET /v1/webhooks` operation can be used as an input to the `DELETE /v1/webhooks/:webhookId` operation to delete a webhook.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
items:
type: array
items:
$ref: '#/components/schemas/Webhook'
pagination:
type: object
properties:
nextLink:
type: string
required:
- items
- pagination
example:
items:
- id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
redactedSigningSecret: whs_fx**********************oVMa
status: active
createdAt: '2025-07-17T09:00:00.000Z'
pagination:
nextLink: https://api.folk.app/v1/webhooks?limit=20&cursor=eyJvZmZzZXQiOjIwfQ%3D%3D
deprecations:
type: array
items:
type: string
example:
- This field is deprecated
required:
- data
example:
data:
items:
- id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
redactedSigningSecret: whs_fx**********************oVMa
status: active
createdAt: '2025-07-17T09:00:00.000Z'
pagination:
nextLink: https://api.folk.app/v1/webhooks?limit=20&cursor=eyJvZmZzZXQiOjIwfQ%3D%3D
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
post:
security:
- bearerApiKeyAuth: []
operationId: createWebhook
summary: Create a webhook
description: Creates a new webhook listening to workspace events.
tags:
- Webhooks
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
maxLength: 255
description: A friendly name for the webhook.
example: My app integration
targetUrl:
type: string
maxLength: 2048
format: uri
description: The URL of the webhook. It must be a publicly accessible URL using the HTTP or HTTPS protocol.
example: https://my-app.com/webhook
subscribedEvents:
type: array
items:
type: object
properties:
eventType:
type: string
enum:
- person.created
- person.updated
- person.deleted
- person.groups_updated
- person.workspace_interaction_metadata_updated
- company.created
- company.updated
- company.deleted
- company.groups_updated
- object.created
- object.updated
- object.deleted
- note.created
- note.updated
- note.deleted
- reminder.created
- reminder.updated
- reminder.deleted
- reminder.triggered
filter:
type: object
properties:
groupId:
type: string
maxLength: 255
objectType:
type: string
maxLength: 255
path:
type: array
items:
type: string
maxLength: 255
maxItems: 3
value:
type: string
maxLength: 255
required:
- eventType
additionalProperties: false
minItems: 1
maxItems: 20
description: The events the webhook is subscribed to, with optional filters.
example:
- eventType: person.created
filter:
groupId: grp_bc984b3f-0386-434d-82d7-a91eb6badd71
required:
- name
- targetUrl
- subscribedEvents
additionalProperties: false
responses:
'200':
description: The created webhook.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/WebhookWithSigningSecret'
deprecations:
type: array
items:
type: string
example:
- This field is deprecated
required:
- data
example:
data:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
signingSecret: whsec_QWFSUzl1QUVoQW1kdWtpTnJRTUFpbXNlZmxLTg==
status: active
createdAt: '2025-07-17T09:00:00.000Z'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
/v1/webhooks/{webhookId}:
get:
security:
- bearerApiKeyAuth: []
operationId: getWebhook
summary: Get a webhook
description: Retrieve an existing webhook in the workspace.
tags:
- Webhooks
parameters:
- schema:
type: string
minLength: 40
maxLength: 40
required: true
description: The ID of the webhook to retrieve.
name: webhookId
in: path
responses:
'200':
description: The retrieved webhook in the workspace.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Webhook'
deprecations:
type: array
items:
type: string
example:
- This field is deprecated
required:
- data
example:
data:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
redactedSigningSecret: whs_fx**********************oVMa
status: active
createdAt: '2025-07-17T09:00:00.000Z'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
patch:
security:
- bearerApiKeyAuth: []
operationId: updateWebhook
summary: Update a webhook
description: Update an existing webhook in the workspace.
tags:
- Webhooks
parameters:
- schema:
type: string
minLength: 40
maxLength: 40
required: true
description: The ID of the webhook to update.
name: webhookId
in: path
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
maxLength: 255
description: A friendly name for the webhook.
example: My app integration
targetUrl:
type: string
maxLength: 2048
format: uri
description: The URL of the webhook. It must be a publicly accessible URL using the HTTP or HTTPS protocol.
example: https://my-app.com/webhook
subscribedEvents:
type: array
items:
type: object
properties:
eventType:
type: string
enum:
- person.created
- person.updated
- person.deleted
- person.groups_updated
- person.workspace_interaction_metadata_updated
- company.created
- company.updated
- company.deleted
- company.groups_updated
- object.created
- object.updated
- object.deleted
- note.created
- note.updated
- note.deleted
- reminder.created
- reminder.updated
- reminder.deleted
- reminder.triggered
filter:
type: object
properties:
groupId:
type: string
maxLength: 255
objectType:
type: string
maxLength: 255
path:
type: array
items:
type: string
maxLength: 255
maxItems: 3
value:
type: string
maxLength: 255
required:
- eventType
additionalProperties: false
minItems: 1
maxItems: 20
description: The events the webhook is subscribed to, with optional filters.
example:
- eventType: person.created
filter:
groupId: grp_bc984b3f-0386-434d-82d7-a91eb6badd71
status:
type: string
enum:
- active
- inactive
description: The status of the webhook.
example: active
additionalProperties: false
responses:
'200':
description: The updated webhook in the workspace.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
type: object
properties:
data:
$ref: '#/components/schemas/Webhook'
deprecations:
type: array
items:
type: string
example:
- This field is deprecated
required:
- data
example:
data:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
redactedSigningSecret: whs_fx**********************oVMa
status: active
createdAt: '2025-07-17T09:00:00.000Z'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
delete:
security:
- bearerApiKeyAuth: []
operationId: deleteWebhook
summary: Delete a webhook
description: Delete an existing webhook in the workspace.
tags:
- Webhooks
parameters:
- schema:
type: string
minLength: 40
maxLength: 40
required: true
description: The ID of the webhook to delete.
name: webhookId
in: path
responses:
'200':
description: The ID of the deleted webhook.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
required:
- id
example:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
deprecations:
type: array
items:
type: string
example:
- This field is deprecated
required:
- data
example:
data:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'403':
$ref: '#/components/responses/Forbidden'
'404':
$ref: '#/components/responses/NotFound'
'422':
$ref: '#/components/responses/UnprocessableEntity'
'429':
$ref: '#/components/responses/TooManyRequests'
'500':
$ref: '#/components/responses/InternalServerError'
'503':
$ref: '#/components/responses/ServiceUnavailable'
components:
responses:
Forbidden:
description: The API key doesn’t have permissions to perform the request.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: FORBIDDEN
message: The API key doesn’t have permissions to perform the request.
documentationUrl: https://developer.folk.app/api-reference/errors#forbidden
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
ServiceUnavailable:
description: The server is overloaded or down for maintenance.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: SERVICE_UNAVAILABLE
message: The service is currently unavailable.
documentationUrl: https://developer.folk.app/api-reference/errors#service-unavailable
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
NotFound:
description: The requested resource doesn’t exist.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: RESOURCE_NOT_FOUND
message: The requested resource was not found.
documentationUrl: https://developer.folk.app/api-reference/errors#not-found
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
InternalServerError:
description: Something went wrong on our end.
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: INTERNAL_SERVER_ERROR
message: An internal server error occurred.
documentationUrl: https://developer.folk.app/api-reference/errors#internal-server-error
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
UnprocessableEntity:
description: The request was unacceptable, often due to missing or invalid parameters.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: UNPROCESSABLE_ENTITY
message: Invalid query parameters
documentationUrl: https://developer.folk.app/api-reference/errors#unprocessable-entity
details:
issues:
- code: too_small
minimum: 1
type: number
inclusive: true
exact: false
message: Number must be greater than or equal to 1
path:
- limit
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
Unauthorized:
description: No valid API key provided.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: UNAUTHORIZED
message: No valid API key provided.
documentationUrl: https://developer.folk.app/api-reference/errors#unauthorized
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
BadRequest:
description: The request was unacceptable, often due to missing an invalid parameter.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: INVALID_REQUEST
message: The request was invalid.
documentationUrl: https://developer.folk.app/api-reference/errors#bad-request
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
TooManyRequests:
description: Too many requests hit the API too quickly. We recommend an exponential backoff of your requests.
headers:
X-RateLimit-Limit:
$ref: '#/components/headers/X-RateLimit-Limit'
X-RateLimit-Remaining:
$ref: '#/components/headers/X-RateLimit-Remaining'
X-RateLimit-Reset:
$ref: '#/components/headers/X-RateLimit-Reset'
Retry-After:
$ref: '#/components/headers/Retry-After'
content:
application/json:
schema:
$ref: '#/components/schemas/Error'
example:
error:
code: RATE_LIMIT_EXCEEDED
message: The rate limit has been exceeded.
documentationUrl: https://developer.folk.app/api-reference/errors#rate-limiting
requestId: 123e4567-e89b-12d3-a456-426614174000
timestamp: '2025-10-01T12:00:00Z'
details:
limit: 1000
remaining: 0
retryAfter: '2025-10-01T12:00:00Z'
headers:
X-RateLimit-Limit:
schema:
type: integer
example: 1000
description: The maximum number of requests that you can make in the current rate limit window.
X-RateLimit-Remaining:
schema:
type: integer
example: 998
description: The number of requests remaining in the current rate limit window.
Retry-After:
schema:
type: integer
example: 60
description: The number of seconds to wait before making a new request after hitting the rate limit.
X-RateLimit-Reset:
schema:
type: integer
example: 1747322958
description: The time at which the current rate limit window resets, in UTC epoch seconds.
schemas:
Error:
type: object
properties:
error:
type: object
properties:
code:
type: string
example: RATE_LIMIT_EXCEEDED
message:
type: string
example: You have exceeded your rate limit.
documentationUrl:
type: string
format: uri
example: https://developer.folk.app/api-reference/errors#rate-limiting
requestId:
type: string
format: uuid
example: 123e4567-e89b-12d3-a456-426614174000
timestamp:
type: string
format: date-time
example: '2025-10-01T12:00:00Z'
details:
type: object
additionalProperties: true
example:
limit: 1000
remaining: 0
retryAfter: '2025-10-01T12:00:00Z'
required:
- code
- message
- documentationUrl
- requestId
- timestamp
required:
- error
description: Error response containing error details.
WebhookWithSigningSecret:
type: object
properties:
id:
type: string
name:
type: string
maxLength: 255
description: A friendly name for the webhook.
example: My app integration
targetUrl:
type: string
maxLength: 2048
format: uri
description: The URL of the webhook.
example: https://my-app.com/webhook
subscribedEvents:
type: array
items:
type: object
properties:
eventType:
type: string
filter:
type: object
properties:
groupId:
type: string
maxLength: 255
objectType:
type: string
maxLength: 255
path:
type: array
items:
type: string
maxLength: 255
maxItems: 3
value:
type: string
maxLength: 255
default: {}
required:
- eventType
maxItems: 20
description: The events the webhook is subscribed to, with optional filters. For more information on how to use filters, see the [create webhook documentation](/api-reference/webhooks/create-a-webhook).
example:
- eventType: person.created
filter: {}
status:
type: string
enum:
- active
- inactive
description: The status of the webhook.
example: active
createdAt:
type: string
format: date-time
description: The date and time the webhook was created.
example: '2025-07-17T09:00:00.000Z'
signingSecret:
type: string
maxLength: 255
description: The signing secret of the webhook.
example: whsec_QWFSUzl1QUVoQW1kdWtpTnJRTUFpbXNlZmxLTg==
required:
- id
- name
- targetUrl
- subscribedEvents
- status
- createdAt
- signingSecret
description: A webhook with a visible signing secret.
example:
id: wbk_8c18c158-d49e-4ad4-90d4-2b197688bac7
name: My app integration
targetUrl: https://my-app.com/webhook
subscribedEvents:
- eventType: person.created
filter: {}
signingSecret: whsec_QWFSUzl1QUVoQW1kdWtpTnJRTUFpbXNlZmxLTg==
status: active
createdAt: '2025-07-17T09:00:00.000Z'
Webhook:
type: object
properties:
id:
type: string
name:
type: string
maxLength:
# --- truncated at 32 KB (34 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/folk/refs/heads/main/openapi/folk-webhooks-api-openapi.yml