Skip to main content

Hooks - Save

Endpoint

/i/hook/save

Overview

Creates a new hook or updates an existing hook using a single endpoint.

Authentication

Countly API supports three authentication methods:

  1. API key query parameter: api_key=YOUR_API_KEY
  2. Auth token query parameter: auth_token=YOUR_AUTH_TOKEN
  3. Auth token header: countly-token: YOUR_AUTH_TOKEN

Permissions

Requires hooks Create permission.

Request Parameters

ParameterTypeRequiredDescription
hook_configJSON String (Object)YesJSON-stringified hook payload for create or update.
app_idStringConditionalRequired for non-global-admin users.
api_keyStringConditionalRequired if auth_token is not provided.
auth_tokenStringConditionalRequired if api_key is not provided.

hook_config Object Structure

FieldTypeRequiredDescription
_idStringNoExisting hook ID. If present, endpoint runs update flow.
nameStringConditionalRequired in create flow (_id absent).
descriptionStringNoHuman-readable hook description.
appsArrayConditionalRequired in create flow; app IDs targeted by this hook.
triggerObjectConditionalRequired in create flow; trigger definition.
trigger.typeStringConditionalTrigger type (for example InternalEventTrigger).
trigger.configurationObjectConditionalTrigger configuration payload for selected type.
effectsArrayConditionalRequired in create flow; effect definitions.
effects[].typeStringConditionalEffect type (for example EmailEffect, HTTPEffect, CustomCodeEffect).
effects[].configurationObjectConditionalEffect-specific configuration object.
enabledBooleanConditionalRequired in create flow.

Decoded create payload example:

{
"name": "Notify Premium Cohort",
"description": "Send email when users enter premium cohort",
"apps": ["6991c75b024cb89cdc04efd2"],
"trigger": {
"type": "InternalEventTrigger",
"configuration": {
"eventType": "/cohort/enter"
}
},
"effects": [
{
"type": "EmailEffect",
"configuration": {
"address": ["ops@example.com"],
"emailTemplate": "User {{uid}} entered premium cohort"
}
}
],
"enabled": true
}

Decoded update payload example:

{
"_id": "65f0cbf8bca6b8e8fbf7f901",
"enabled": false,
"description": "Temporarily disabled"
}

Configuration Impact

These hooks settings affect runtime behavior after saving, but do not change the immediate save response shape:

  • refreshRulesPeriod: controls how quickly saved rule changes are loaded into runtime cache.
  • pipelineInterval and batchActionSize: affect execution throughput and latency when rules trigger.
  • requestLimit and timeWindowForRequestLimit: can throttle effect execution per rule at runtime.

Response

Success Response

Create flow (hook_config._id absent):

"65f0cbf8bca6b8e8fbf7f901"

Update flow (hook_config._id provided):

{
"_id": "65f0cbf8bca6b8e8fbf7f901",
"name": "Notify Premium Cohort",
"description": "Temporarily disabled",
"apps": ["6991c75b024cb89cdc04efd2"],
"trigger": {
"type": "InternalEventTrigger",
"configuration": {
"eventType": "/cohort/enter"
}
},
"effects": [
{
"type": "EmailEffect",
"configuration": {
"address": ["ops@example.com"],
"emailTemplate": "User {{uid}} entered premium cohort"
}
}
],
"enabled": false,
"createdBy": "65d4a6d4d8d9a17e2f5b1001",
"created_at": 1700000000000
}

Response Fields

FieldTypeDescription
(root value)StringCreated hook ID in create flow.
_idStringUpdated hook ID in update flow response object.
appsArrayTarget app IDs configured for the hook.
triggerObjectTrigger configuration currently stored for the hook.
effectsArrayEffect list currently stored for the hook.
enabledBooleanCurrent active state of the hook.

Error Responses

  • 400
{
"result": "Missing parameter \"api_key\" or \"auth_token\""
}
  • 400
{
"result": "Token not valid"
}
  • 400
{
"result": "Invalid hookConfig"
}
  • 400
{
"result": "Not enough args"
}
  • 400
{
"result": "Invalid configuration for effects"
}
  • 401
{
"result": "No app_id provided"
}
  • 401
{
"result": "User does not exist"
}
  • 401
{
"result": "User does not have right"
}
  • 401
{
"result": "User is locked"
}
  • 401
{
"result": "App does not exist"
}
  • 401
{
"result": "Token is invalid"
}
  • 500
{
"result": "No result found"
}
  • 500
{
"result": "Failed to save an hook"
}
  • 500
{
"result": "Failed to create an hook"
}

Behavior/Processing

Behavior Modes

ModeTriggerProcessing PathResponse Shape
Create hook_id absentValidates payload, adds createdBy and created_at, inserts into hooks.Raw root hook ID string
Update hook_id presentUpdates existing hook document by ID and returns updated document.Raw root hook object

Impact on Other Data

  • Writes hook data to countly.hooks.
  • Dispatches system log entries for create or update actions.

Audit & System Logs

Successful writes dispatch /systemlogs with these actions:

  • hook_created
  • hook_updated

Database Collections

CollectionUsed forData touched by this endpoint
countly.membersAuthentication and permission checksReads member account and access metadata.
countly.appsApp validation for non-global-admin usersReads app context during permission validation.
countly.hooksHook storageInserts new hook documents or updates existing hook documents.

Examples

Create hook

/i/hook/save?
app_id=6991c75b024cb89cdc04efd2&
api_key=YOUR_API_KEY&
hook_config={
"name":"Notify Premium Cohort",
"description":"Send email when users enter premium cohort",
"apps":["6991c75b024cb89cdc04efd2"],
"trigger":{"type":"InternalEventTrigger","configuration":{"eventType":"/cohort/enter"}},
"effects":[{"type":"EmailEffect","configuration":{"address":["ops@example.com"],"emailTemplate":"User {{uid}} entered premium cohort"}}],
"enabled":true
}

Update hook

/i/hook/save?
app_id=6991c75b024cb89cdc04efd2&
api_key=YOUR_API_KEY&
hook_config={
"_id":"65f0cbf8bca6b8e8fbf7f901",
"enabled":false,
"description":"Temporarily disabled"
}

Operational Considerations

  • Saved changes are not applied to runtime execution instantly; rule cache refresh follows refreshRulesPeriod.
  • Large effect lists increase execution cost when the rule triggers.

Limitations

  • If update flow runs with a non-existent _id, response is 500 with No result found.
  • HTTPEffect validates URL format and rejects localhost/loopback targets at validation stage.

Last Updated

2026-02-17