Menu

Reference

Campaigns

Campaigns: 13 operations (campaign_leads.upsert_enroll, campaigns.list, campaigns.create, campaigns.get, campaigns.update, campaigns.delete, campaigns.archive, campaigns.clone, campaigns.pause, campaigns.resume, campaigns.start, campaigns.stats, campaigns.steps.replace).

MethodPathOperation
POST/v1/campaign-leadscampaign_leads.upsert_enroll
GET/v1/campaignscampaigns.list
POST/v1/campaignscampaigns.create
GET/v1/campaigns/{campaign_id}campaigns.get
PATCH/v1/campaigns/{campaign_id}campaigns.update
DELETE/v1/campaigns/{campaign_id}campaigns.delete
POST/v1/campaigns/{campaign_id}/archivecampaigns.archive
POST/v1/campaigns/{campaign_id}/clonecampaigns.clone
POST/v1/campaigns/{campaign_id}/pausecampaigns.pause
POST/v1/campaigns/{campaign_id}/resumecampaigns.resume
POST/v1/campaigns/{campaign_id}/startcampaigns.start
GET/v1/campaigns/{campaign_id}/statscampaigns.stats
PUT/v1/campaigns/{campaign_id}/stepscampaigns.steps.replace

campaign_leads.upsert_enroll

POST/v1/campaign-leads

Upsert one lead, then enroll it into a campaign (the Clay add-to-campaign column).

A refusal to enroll (already in a campaign, opted out) is a 200 with skipped_reason; the lead keeps the fields the upsert wrote.

Operation idcampaign_leads.upsert_enroll
Scopesleads:write, enrollments:write
Rate class`write`, plus leads_created_day
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys and Clay compatible keys

Request body

FieldTypeRequiredDescription
campaign_idanynoRequired: a campaign of the key's workspace.
custom_fieldsanyno{ key: value } of the workspace's custom fields.
emailanyno
external_idanyno
fb_handleanyno
first_nameanyno
folderanynoFolder NAME, created when missing.
followersanynoA number, or a numeric string.
ig_handleanynoRequired for every lead: the matching key.
last_nameanyno
mergeanynofill_empty (default) or overwrite.
nameanyno
nicheanyno
notesanyno
phoneanyno
profile_urlanyno
rep_ig_usernameanynoOne of the key's reps; omitted, the least loaded one.
skip_if_in_any_campaignanynoBoolean, default true.
tagsanynoAn array of tags or one comma-separated string, at most 20.

Response 200

JSON of type object.

Errors

StatusCodeWhen
400`CUSTOM_FIELD_UNKNOWN_400`custom_fields names a key this workspace has not defined. Create it with POST /v1/custom-fields first.
404`CAMPAIGN_NOT_FOUND_404`No campaign with that campaign_id in this API key's workspace.
404`LEAD_NOT_FOUND_404`The lead was deleted while the call ran; nothing was enrolled.
404`REP_NOT_FOUND_404`No rep with this id or username that this API key may use.
409`CAMPAIGN_ARCHIVED_409`The campaign is archived and takes no new leads.
409`LEAD_AMBIGUOUS_409`More than one lead in this workspace has that Instagram handle.
409`REP_NONE_AVAILABLE_409`This API key has no active rep to enroll leads on.
429`LEADS_DAILY_LIMIT_429`The organization reached its daily limit of leads created through the API.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaign-leads" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "ig_handle": "jane.doe",
  "first_name": "Jane",
  "external_id": "crm-1042",
  "campaign_id": "3f6c2a9e-8b1d-4c7a-9e2f-5d4b3a2c1e0f"
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "ig_handle": {
      "description": "Required for every lead: the matching key."
    },
    "name": {},
    "first_name": {},
    "last_name": {},
    "fb_handle": {},
    "profile_url": {},
    "niche": {},
    "followers": {
      "description": "A number, or a numeric string."
    },
    "notes": {},
    "tags": {
      "description": "An array of tags or one comma-separated string, at most 20."
    },
    "folder": {
      "description": "Folder NAME, created when missing."
    },
    "custom_fields": {
      "description": "{ key: value } of the workspace's custom fields."
    },
    "external_id": {},
    "email": {},
    "phone": {},
    "merge": {
      "description": "fill_empty (default) or overwrite."
    },
    "campaign_id": {
      "description": "Required: a campaign of the key's workspace."
    },
    "rep_ig_username": {
      "description": "One of the key's reps; omitted, the least loaded one."
    },
    "skip_if_in_any_campaign": {
      "description": "Boolean, default true."
    }
  }
}
Response 200
{
  "anyOf": [
    {
      "type": "object",
      "properties": {
        "lead_id": {
          "type": "string"
        },
        "result": {
          "type": "string"
        },
        "updated_fields": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "enrolled": {
          "type": "boolean"
        },
        "skipped_reason": {
          "type": [
            "string",
            "null"
          ]
        },
        "campaign_id": {
          "type": "string"
        },
        "rep_ig_username": {
          "type": [
            "string",
            "null"
          ]
        },
        "queue_state": {
          "type": [
            "string",
            "null"
          ]
        },
        "lead_status": {
          "type": "string"
        }
      },
      "required": [
        "lead_id",
        "result",
        "updated_fields",
        "enrolled",
        "skipped_reason",
        "campaign_id",
        "rep_ig_username",
        "queue_state",
        "lead_status"
      ],
      "additionalProperties": false
    },
    {
      "type": "object",
      "properties": {
        "replayed": {
          "type": "boolean",
          "const": true
        },
        "status": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "ids": {
          "type": "object",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {
            "type": "string"
          }
        }
      },
      "required": [
        "replayed",
        "status",
        "ids"
      ],
      "additionalProperties": false
    }
  ]
}

campaigns.list

GET/v1/campaigns

List the workspace's campaigns, newest first.

Offset paging (limit, offset) is kept for existing integrations; cursor (from next_cursor) is the keyset alternative and cannot be combined with offset. limit and offset out of range are clamped.

Operation idcampaigns.list
Scopescampaigns:read
Rate class`read`
IdempotencyNot applicable
KeysDeveloper keys and Clay compatible keys

Query parameters

NameTypeRequiredDescription
status"active" | "paused" | "completed" | "archived"no
limitintegerno1 to 200, default 100
offsetintegerno0 to 1000000
cursorstringno1 to 2048 characters

Response 200

FieldTypeRequiredDescription
dataobject[]yes
has_morebooleanyes
limitintegeryes-9007199254740991 to 9007199254740991
next_cursorstring | nullyes
offsetintegeryes-9007199254740991 to 9007199254740991
totalintegeryes-9007199254740991 to 9007199254740991

Errors

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl "https://api.dmhero.ai/v1/campaigns" \
  -H "Authorization: Bearer $DMHERO_API_KEY"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "data": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "paused",
              "completed",
              "archived"
            ]
          },
          "timezone": {
            "type": "string"
          },
          "business_hours": {
            "type": "string"
          },
          "send_weight": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "send_rank": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "enrolled_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
          },
          "active_count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Of those, the ones still in the sequence."
          },
          "steps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "step_order": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "template_id": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "delay_days": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991
                },
                "platform": {
                  "type": "string"
                },
                "message_mode": {
                  "type": "string",
                  "enum": [
                    "template",
                    "ai"
                  ],
                  "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
                }
              },
              "required": [
                "id",
                "step_order",
                "template_id",
                "delay_days",
                "platform",
                "message_mode"
              ],
              "additionalProperties": false
            }
          },
          "created_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time",
            "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
          }
        },
        "required": [
          "id",
          "name",
          "description",
          "status",
          "timezone",
          "business_hours",
          "send_weight",
          "send_rank",
          "enrolled_count",
          "active_count",
          "created_at",
          "updated_at"
        ],
        "additionalProperties": false
      }
    },
    "total": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "limit": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "offset": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "has_more": {
      "type": "boolean"
    },
    "next_cursor": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "data",
    "total",
    "limit",
    "offset",
    "has_more",
    "next_cursor"
  ],
  "additionalProperties": false
}

campaigns.create

POST/v1/campaigns

Create a campaign, optionally with its steps. It starts paused.

Every step's template is checked before anything is written. Start the campaign with POST /v1/campaigns/{campaign_id}/start.

Operation idcampaigns.create
Scopescampaigns:write
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys

Request body

FieldTypeRequiredDescription
namestringyes1 to 80 characters
business_hoursstringnoFree text the AI Setter reads when it books.. at most 200 characters
descriptionstring | nullno
send_rankintegerno0 to 1000
send_weightintegerno1 to 100
stepsobject[]noThe whole sequence, in order: the first item is step 1.. 1 to 10 items
timezonestringnoIANA timezone; defaults to the workspace's.. at most 64 characters

Response 201

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`TEMPLATE_NOT_FOUND_404`A step names a template that is not in the key's workspace. Nothing was written.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "string"
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 80
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "timezone": {
      "description": "IANA timezone; defaults to the workspace's.",
      "type": "string",
      "maxLength": 64
    },
    "business_hours": {
      "description": "Free text the AI Setter reads when it books.",
      "type": "string",
      "maxLength": 200
    },
    "send_weight": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "send_rank": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "steps": {
      "minItems": 1,
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "template_id": {
            "type": "string",
            "maxLength": 64,
            "description": "A template of this workspace (uuid)."
          },
          "delay_days": {
            "type": "integer",
            "minimum": 0,
            "maximum": 90,
            "description": "Days after the previous step (the first step: after enrollment)."
          }
        },
        "required": [
          "template_id",
          "delay_days"
        ]
      },
      "description": "The whole sequence, in order: the first item is step 1."
    }
  },
  "required": [
    "name"
  ]
}
Response 201
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.get

GET/v1/campaigns/{campaign_id}

Get one campaign with its steps.

Operation idcampaigns.get
Scopescampaigns:read
Rate class`read`
IdempotencyNot applicable
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl "https://api.dmhero.ai/v1/campaigns/string" \
  -H "Authorization: Bearer $DMHERO_API_KEY"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.update

PATCH/v1/campaigns/{campaign_id}

Update a campaign's settings.

status cannot be set here: use the start, pause, resume and archive endpoints.

Operation idcampaigns.update
Scopescampaigns:write
Rate class`write`
IdempotencyNot applicable
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Request body

FieldTypeRequiredDescription
business_hoursstringnoFree text the AI Setter reads when it books.. at most 200 characters
descriptionstring | nullno
namestringno1 to 80 characters
send_rankintegerno0 to 1000
send_weightintegerno1 to 100
statusstringnoRefused: use the control endpoints.. at most 32 characters
timezonestringnoIANA timezone; defaults to the workspace's.. at most 64 characters

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
400`CAMPAIGN_STATUS_VIA_CONTROL_400`The body sets status; use start, pause, resume or archive.
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X PATCH "https://api.dmhero.ai/v1/campaigns/string" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "Webinar follow-up",
  "send_weight": 2
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 80
    },
    "description": {
      "anyOf": [
        {
          "type": "string",
          "maxLength": 500
        },
        {
          "type": "null"
        }
      ]
    },
    "timezone": {
      "description": "IANA timezone; defaults to the workspace's.",
      "type": "string",
      "maxLength": 64
    },
    "business_hours": {
      "description": "Free text the AI Setter reads when it books.",
      "type": "string",
      "maxLength": 200
    },
    "send_weight": {
      "type": "integer",
      "minimum": 1,
      "maximum": 100
    },
    "send_rank": {
      "type": "integer",
      "minimum": 0,
      "maximum": 1000
    },
    "status": {
      "description": "Refused: use the control endpoints.",
      "type": "string",
      "maxLength": 32
    }
  }
}
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.delete

DELETE/v1/campaigns/{campaign_id}

Delete a campaign with its steps and enrollments.

Operation idcampaigns.delete
Scopescampaigns:write
Rate class`write`
IdempotencyNot applicable
KeysDeveloper keys
DestructiveYes: it removes or stops something that cannot be restored by repeating the call

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Query parameters

NameTypeRequiredDescription
confirmbooleannoMust be true.

Response 204

No body.

Errors

StatusCodeWhen
400`CONFIRM_REQUIRED_400`This action cannot be undone; send confirm=true.
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X DELETE "https://api.dmhero.ai/v1/campaigns/string?confirm=true" \
  -H "Authorization: Bearer $DMHERO_API_KEY"

campaigns.archive

POST/v1/campaigns/{campaign_id}/archive

Archive a campaign: every enrollment stops sending.

Operation idcampaigns.archive
Scopescampaigns:control
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys
DestructiveYes: it removes or stops something that cannot be restored by repeating the call

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Request body

FieldTypeRequiredDescription
confirmbooleannoMust be true.

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
400`CONFIRM_REQUIRED_400`This action cannot be undone; send confirm=true.
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns/string/archive" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "confirm": true
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "confirm": {
      "description": "Must be true.",
      "type": "boolean"
    }
  }
}
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.clone

POST/v1/campaigns/{campaign_id}/clone

Copy a campaign and its steps, without its enrollments. The copy starts paused.

Operation idcampaigns.clone
Scopescampaigns:write
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Request body

FieldTypeRequiredDescription
namestringno1 to 80 characters

Response 201

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns/string/clone" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{
  "name": "string"
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "name": {
      "type": "string",
      "minLength": 1,
      "maxLength": 80
    }
  }
}
Response 201
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.pause

POST/v1/campaigns/{campaign_id}/pause

Pause an active campaign.

active -> paused. Nothing more is sent until it is resumed. A campaign that is already paused is answered as is.

Operation idcampaigns.pause
Scopescampaigns:control
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.
409`CAMPAIGN_STATUS_CONFLICT_409`The campaign is not in a status this transition starts from, or its status changed meanwhile.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns/string/pause" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.resume

POST/v1/campaigns/{campaign_id}/resume

Resume a paused campaign.

paused -> active, without the steps check of start. A campaign that is already active is answered as is.

Operation idcampaigns.resume
Scopescampaigns:control
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.
409`CAMPAIGN_STATUS_CONFLICT_409`The campaign is not in a status this transition starts from, or its status changed meanwhile.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns/string/resume" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.start

POST/v1/campaigns/{campaign_id}/start

Start a paused campaign.

paused -> active. The extension then sends each enrollment's due step at its own pace. A campaign that is already active is answered as is.

Operation idcampaigns.start
Scopescampaigns:control
Rate class`write`
Idempotency`Idempotency-Key` accepted
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Response 200

FieldTypeRequiredDescription
active_countintegeryesOf those, the ones still in the sequence.. -9007199254740991 to 9007199254740991
business_hoursstringyes
created_atdate-timeyes
descriptionstring | nullyes
enrolled_countintegeryesEnrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones.. -9007199254740991 to 9007199254740991
idstringyes
namestringyes
send_rankintegeryes-9007199254740991 to 9007199254740991
send_weightintegeryes-9007199254740991 to 9007199254740991
status"active" | "paused" | "completed" | "archived"yes
timezonestringyes
updated_atdate-timeyes
stepsobject[]no

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.
409`CAMPAIGN_NO_STEPS_409`The campaign has no steps yet.
409`CAMPAIGN_STATUS_CONFLICT_409`The campaign is not in a status this transition starts from, or its status changed meanwhile.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X POST "https://api.dmhero.ai/v1/campaigns/string/start" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "description": {
      "type": [
        "string",
        "null"
      ]
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "paused",
        "completed",
        "archived"
      ]
    },
    "timezone": {
      "type": "string"
    },
    "business_hours": {
      "type": "string"
    },
    "send_weight": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "send_rank": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "enrolled_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Enrollments the key may see: its reps' ones, and for an unrestricted key also the unassigned ones."
    },
    "active_count": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991,
      "description": "Of those, the ones still in the sequence."
    },
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    },
    "created_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$"
    }
  },
  "required": [
    "id",
    "name",
    "description",
    "status",
    "timezone",
    "business_hours",
    "send_weight",
    "send_rank",
    "enrolled_count",
    "active_count",
    "created_at",
    "updated_at"
  ],
  "additionalProperties": false
}

campaigns.stats

GET/v1/campaigns/{campaign_id}/stats

A campaign's funnel and enrollment numbers.

funnel (active enrollments by current step) and withheld_custom (active enrollments held back for a missing custom field value) are as of now. enrolled, active, completed and replied cover the enrollments of the last days days when given. Every number covers only the enrollments the key may see.

Operation idcampaigns.stats
Scopescampaigns:read
Rate class`read`, costs 5 per call
IdempotencyNot applicable
KeysDeveloper keys
RepsA key restricted to reps sees only data of its own reps

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Query parameters

NameTypeRequiredDescription
daysintegerno1 to 365

Response 200

FieldTypeRequiredDescription
activeintegeryes-9007199254740991 to 9007199254740991
completedintegeryes-9007199254740991 to 9007199254740991
enrolledintegeryes-9007199254740991 to 9007199254740991
funnelobject[]yes
repliedintegeryes-9007199254740991 to 9007199254740991
withheld_customobjectyes

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl "https://api.dmhero.ai/v1/campaigns/string/stats" \
  -H "Authorization: Bearer $DMHERO_API_KEY"
JSON Schema
Response 200
{
  "type": "object",
  "properties": {
    "funnel": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "step": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "count": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        },
        "required": [
          "step",
          "count"
        ],
        "additionalProperties": false
      }
    },
    "enrolled": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "active": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "completed": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "replied": {
      "type": "integer",
      "minimum": -9007199254740991,
      "maximum": 9007199254740991
    },
    "withheld_custom": {
      "type": "object",
      "properties": {
        "total": {
          "type": "integer",
          "minimum": -9007199254740991,
          "maximum": 9007199254740991
        },
        "by_key": {
          "type": "object",
          "propertyNames": {
            "type": "string"
          },
          "additionalProperties": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          }
        }
      },
      "required": [
        "total",
        "by_key"
      ],
      "additionalProperties": false
    }
  },
  "required": [
    "funnel",
    "enrolled",
    "active",
    "completed",
    "replied",
    "withheld_custom"
  ],
  "additionalProperties": false
}

campaigns.steps.replace

PUT/v1/campaigns/{campaign_id}/steps

Replace a campaign's whole step sequence.

One transaction: a refused step leaves the old sequence intact. Enrollments keep their current step number, so a lead on step 2 continues with the new step 2. Each step keeps the message_mode the step with the same step_order had; a new step is template.

Operation idcampaigns.steps.replace
Scopescampaigns:write
Rate class`write`
IdempotencyNot applicable
KeysDeveloper keys

Path parameters

NameTypeRequiredDescription
campaign_idstringyesCampaign id (uuid). at most 64 characters

Request body

FieldTypeRequiredDescription
stepsobject[]yesThe whole sequence, in order: the first item is step 1.. 1 to 10 items

Response 200

FieldTypeRequiredDescription
stepsobject[]yes

Errors

StatusCodeWhen
404`CAMPAIGN_NOT_FOUND_404`No campaign with this id exists in the key's workspace.
404`TEMPLATE_NOT_FOUND_404`A step names a template that is not in the key's workspace. Nothing was written.

Every operation can also answer the shared errors: authentication, scopes, rate limits and validation.

Example

bash
curl -X PUT "https://api.dmhero.ai/v1/campaigns/string/steps" \
  -H "Authorization: Bearer $DMHERO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "steps": [
    {
      "template_id": "string",
      "delay_days": 0
    }
  ]
}'
JSON Schema
Request body
{
  "type": "object",
  "properties": {
    "steps": {
      "minItems": 1,
      "maxItems": 10,
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "template_id": {
            "type": "string",
            "maxLength": 64,
            "description": "A template of this workspace (uuid)."
          },
          "delay_days": {
            "type": "integer",
            "minimum": 0,
            "maximum": 90,
            "description": "Days after the previous step (the first step: after enrollment)."
          }
        },
        "required": [
          "template_id",
          "delay_days"
        ]
      },
      "description": "The whole sequence, in order: the first item is step 1."
    }
  },
  "required": [
    "steps"
  ]
}
Response 200
{
  "type": "object",
  "properties": {
    "steps": {
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "step_order": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "template_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "delay_days": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "platform": {
            "type": "string"
          },
          "message_mode": {
            "type": "string",
            "enum": [
              "template",
              "ai"
            ],
            "description": "Read only. `ai`: the step sends a first message written for each lead, and `template_id` is its fallback, sent only when no such message can be written. `template`: the step sends `template_id`. Set in the app; `campaigns.steps.replace` keeps each step's mode by `step_order`."
          }
        },
        "required": [
          "id",
          "step_order",
          "template_id",
          "delay_days",
          "platform",
          "message_mode"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "steps"
  ],
  "additionalProperties": false
}
Campaigns | DM Hero Developers