Kerux
Start free trial

Kerux · OpenAPI 3.1 (JSON)

Kerux API v1

Base URL https://www.usekerux.com/api/v1. Create a key in Developers and send it as Authorization: Bearer sf_live_…. JSON in and out; answers are { data }, errors { error: { code, message, details } }.

Integration recipes

Step-by-step guides for using a tool with Kerux: the connection (auth type and header), the exact HTTP steps or webhook mapping from the vendor's docs, an example request and answer, and how to test with one lead.

Account

GET /v1/me

The key's workspace, scopes and mode. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/me" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Leads

GET /v1/leads

List leads (newest first, or highest engagement score first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads

Create a lead. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/leads/bulk

Create or update up to 1,000 leads, matched by LinkedIn URL. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/bulk" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/leads/{id}

Get a lead with its lists and where it came from (its first ad or UTM touch). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/leads/{id}

Update a lead's fields. Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/leads/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/leads/{id}

Delete a lead (and its campaign progress). Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/leads/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/leads/{id}/timeline

The lead's timeline (last 100 entries, newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/timeline" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads/{id}/tags

Add tags. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/tags" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/leads/{id}/tags/{tag}

Remove a tag. Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/leads/<id>/tags/<tag>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/leads/{id}/attribution

Where the lead came from: its first touch (an ad lead form or a visit's UTMs) and every touch. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/attribution" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/leads/{id}/owner

Assign the lead to a teammate (a workspace member), or take the owner off with null. Scope leads:write.

curl -X PUT "https://www.usekerux.com/api/v1/leads/<id>/owner" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/leads/{id}/notes

The lead's notes (newest first), by people and by campaign steps. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/notes" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads/{id}/notes

Add a note to the lead. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/notes" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/leads/{id}/ai-findings

The lead's latest 'Research with AI online' result (kept 30 days): summaries, news, hook, website, email found on a public page with its source. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/ai-findings" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/leads/{id}/engagement

The lead's engagement score, when it became hot, and its latest signals (newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/engagement" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/business-cards/scan

Read a photo of one or more business cards into draft leads (nothing is saved). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/business-cards/scan" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/business-cards

Save one reviewed business card as a lead (source "business_card"). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/business-cards" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Enrichment

POST /v1/enrichment

Enrich leads or companies with the workspace's providers (queued; see /enrichment/jobs). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/enrichment" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/enrichment/jobs

Recent enrichment jobs with every provider tried and the values filled. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/enrichment/jobs" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Templates

GET /v1/templates

List message templates (alphabetical). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/templates" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/templates

Create a message template (plain text with {{variables}}; names are unique; optional subject for InMail and email steps). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/templates" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/templates/{id}

Rename or edit a message template (subject: null or "" removes it). Scope workflows:write.

curl -X PATCH "https://www.usekerux.com/api/v1/templates/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/templates/{id}

Delete a message template (campaigns that used it keep their text). Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/templates/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Signals

GET /v1/signals

List signal watches (posts and company pages watched from your LinkedIn accounts). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/signals" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/signals

Watch a LinkedIn post or company page from one of your accounts (up to 5 active watches per account, sharing at most 8 reads a day per account; a post stops after 7 days unless stop_after_days says otherwise). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/signals" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/signals/{id}

Pause or resume a signal watch, or change when a post watch stops (resuming counts toward the 5 active watches per account). Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/signals/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/signals/{id}

Stop and remove a signal watch (the leads it added stay). Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/signals/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/signals/icp

The ideal customer profile people from signals are checked against. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/signals/icp" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/signals/icp

Set the ideal customer profile (only the fields sent change). Scope leads:write.

curl -X PUT "https://www.usekerux.com/api/v1/signals/icp" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/signals/judgments

People from signals, checked against the ICP: checks, score and decision (newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/signals/judgments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/signals/judgments/{id}/decision

DM (puts the person in the campaign) or Skip, whatever the score said. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/signals/judgments/<id>/decision" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Companies

GET /v1/companies

List companies (alphabetical) with their number of leads. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/companies" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/companies

Create a company (leads join it when their company name matches). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/companies" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/companies/{id}

Get a company with its leads (up to 200, newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/companies/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/companies/{id}

Update a company's fields (renaming keeps its leads linked). Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/companies/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Lists

GET /v1/lists

Lead lists. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/lists" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/lists

Create a list. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/lists" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/lists/{id}/members

Add (or with remove=true, take out) leads. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/lists/<id>/members" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Workflows

GET /v1/workflows

Campaigns (sequences and automations). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows

Create a campaign (draft). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workflows/{id}

A campaign with its draft, live definition and problems, and its steps in plain words (numbered like the canvas). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/workflows/{id}

Change a campaign's settings. The name, sending schedule, reply types, re-entry, mark-as-read, email tracking and the manual trigger change at once; the rest goes into the draft (publish to apply). Turning the manual trigger off while contacts wait in the Contacts box needs waiting_leads_action (else 422 WAITING_LEADS_NEED_CHOICE). manual_auto_start true and waiting_leads_action start start people, so they need enrollments:write too. Scope workflows:write.

curl -X PATCH "https://www.usekerux.com/api/v1/workflows/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/duplicate

Copy a campaign's steps and settings into a new draft (no leads). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/duplicate" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PUT /v1/workflows/{id}/draft

Replace the draft definition (validated; live leads are untouched until you publish). Scope workflows:write.

curl -X PUT "https://www.usekerux.com/api/v1/workflows/<id>/draft" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/draft/changes

Apply step changes to the draft, the same ones Ask AI proposes (add a step after/before a step or at the end, edit a message or a wait, remove a step). Checked against an allowlist: no HTTP or webhook steps, links or secrets. Never publishes. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/draft/changes" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/validate

Check a definition without saving it. Scope workflows:read.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/validate" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/publish

Publish the draft (live edit). Leads on removed steps need a migration map. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/publish" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/pause

Pause a campaign. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/pause" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/resume

Resume a campaign. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/resume" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/archive

Archive a campaign. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/archive" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workflows/{id}/stats

Live counters and results per step. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/stats" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/triggers

Trigger URLs of a campaign (POST a lead to the URL to add it). Scope workflows:write.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/triggers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows/{id}/triggers

Create a trigger URL. With signed=true, the signing secret is in this answer only; with icp=true, people are checked against the ICP first. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/triggers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/triggers/{id}

Turn the ICP check on or off for a trigger URL. Scope workflows:write.

curl -X PATCH "https://www.usekerux.com/api/v1/triggers/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/triggers/{id}

Turn off a trigger URL for good. Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/triggers/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/event-triggers

A campaign's Kerux triggers (lead added, tag added/removed, field changed, date reminder, schedule, trigger link, ICP fit score changed, pipeline stage changed, lead became hot, engagement score changed, lead replied, note added, task added, completed or due, do not contact, LinkedIn account needs attention...). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/event-triggers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows/{id}/event-triggers

Add a Kerux trigger. Each event takes its own fields: lead_created (sources), tag_added / tag_removed (tag), field_changed (field, to), date_reminder (field, days, when, yearly, time, timezone), schedule (every, days, time, timezone, list_id or tag), segment (segment_id: everyone in the smart segment enters, and people who match later, checked every 10 minutes), link_clicked (name, url), score_changed (min_score), message_read (workflow_id: only that campaign's messages; a lead seeing a LinkedIn message, only people who share read receipts), whatsapp_reply (no fields: a lead replied on WhatsApp to a connected number), sms_reply (no fields: a lead texted back to one of your Twilio numbers; a STOP never starts anything), account_attention (problems: locked, restricted, signin, removed, down; the run's lead is the account itself, and {{trigger.account_name}}, {{trigger.account_problem}}, {{trigger.account_fix}} say what happened), message_reacted (emoji, optional), email_opened (no fields), email_clicked (link, optional: only links containing it), meeting_booked / meeting_cancelled (no fields), meeting_soon (hours: 0.25 to 72, default 24; late_bookings: skip or send; a lead's booked meeting starts in that many hours: the campaign's steps remind them with {{meeting.start}}, a cancelled, moved or started meeting never gets the reminder and a moved one gets a new one for the new time), stage_changed (from_stage, to_stage: pipeline stage ids, optional, "none" = off the board; {{trigger.from_stage}} and {{trigger.to_stage}} say where it moved), engagement_hot (no fields: the lead's engagement score reached the workspace's hot threshold, GET /workspace/engagement; {{trigger.engagement_score}}), engagement_changed (min_score, optional: the lead's engagement score went up, or only when it reaches that number; {{trigger.engagement_score}}), reply_received (channels, optional: linkedin, email, sms, whatsapp; a lead replied, never a STOP or an unsubscribe; {{trigger.reply_channel}}, {{trigger.reply_text}}), note_added (contains, optional; {{trigger.note}}), task_added / task_completed (no fields; {{trigger.task_title}}, {{trigger.task_due}}), task_due (timing: before or overdue, hours: 0 to 168, default 1; once per task and due time), do_not_contact (direction: added or removed, channels, optional: all, email, sms, whatsapp; a lead on the list for every channel can't enter a campaign). score_changed is the ICP fit score, not engagement.. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/event-triggers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/event-triggers/{id}

Remove a Kerux trigger. Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/event-triggers/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/problems

What stops this campaign now: accounts that can't send and leads that need a person. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/problems" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/review

The campaign review (the builder's Review): what makes the draft get nowhere (people who accept never get a message, no message asks for anything, messages that never name the offer, leads left with nothing, too many or too few messages), and the last AI review. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/review" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/attention

Leads that need a person in this campaign (optionally on one step): the exact reason, the step and its app, and the fixes that apply (the builder's Needs attention window). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/attention" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows/{id}/attention/retry

Retry now: leads paused for missing data are rendered again from the live step (they stop again if a value is still missing); unconfirmed sends are never retried here. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/attention/retry" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workflows/{id}/waiting-leads

People in a campaign's Contacts box: waiting for its launch, or for Start when the manual trigger's auto-start is off. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/waiting-leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows/{id}/preflight

Preflight and launch forecast for launching or adding these leads (read-only, changes nothing). Scope workflows:read.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/preflight" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/from-description

Create a campaign draft from a description, like the app's Create with AI (one AI use; when the AI can't answer, the rules build it from the description's words). Never publishes, launches or sends; the answer lists the steps and what is left to do. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/from-description" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/draft/changes/preview

Preview step changes before applying them (the same changes and allowlist as POST /workflows/{id}/draft/changes): what Apply would do, every text in full, and what would be left out. Saves nothing. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/draft/changes/preview" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/launch

Launch a campaign after its preflight (like the app's Launch): publishes the draft the first time, starts the leads given and everyone waiting in its Contacts box. Refused with 422 PREFLIGHT_BLOCKED (details.checks) when something blocks it. It starts people, so it needs enrollments:write too. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/launch" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/lead-form-triggers

Start the campaign when a lead form is submitted: provider "*" (any source), "meta" or a form tool; page_id "*" (any page or URL), a Facebook Page id or a form URL id; optional forms. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/lead-form-triggers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/triggers/{id}/form

The hosted form (survey or quiz) on a trigger URL, and its public page. Scope workflows:write.

curl -X GET "https://www.usekerux.com/api/v1/triggers/<id>/form" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/triggers/{id}/form

Add or replace the hosted form on a trigger URL: a public page whose submissions join the campaign. Fields can be survey questions (single / multiple choice, dropdown, rating, yes / no) saved to lead custom fields, and the form can be a quiz whose total score is saved to a custom field. Scope workflows:write.

curl -X PUT "https://www.usekerux.com/api/v1/triggers/<id>/form" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/triggers/{id}/form

Remove the hosted form from a trigger URL (the URL itself keeps working for API posts). Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/triggers/<id>/form" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Enrollments

POST /v1/workflows/{id}/test-runs

Test a launched campaign on one lead: all of it, from a step, or only one step; optionally as a rehearsal (nothing sent on LinkedIn or by email). Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/test-runs" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/enrollments

Add leads to a published campaign (by id, or upserted from lead objects). With the manual trigger's auto-start off they wait in its Contacts box (held) until POST /workflows/{id}/waiting-leads/start. With wait_for_launch=true, leads added to a campaign that was never launched wait in its Contacts box (held) and enter when it is launched (POST /workflows/{id}/launch), instead of a 422 WORKFLOW_NOT_PUBLISHED. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/enrollments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/enrollments

Where leads are, and every run (enrollment history): filter by campaign, state, step, lead, reason or when they entered. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/enrollments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/enrollments/{id}

One lead's place in one campaign, with the reason it waits. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/enrollments/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/enrollments/{id}/move

Move the lead to another step (a done LinkedIn step never repeats unless run_again). Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/move" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/move-to-workflow

Move the lead to another campaign. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/move-to-workflow" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/exit

Take the lead out of the campaign. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/exit" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/pause

Pause one lead (its queued action waits). Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/pause" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/resume

Resume a paused lead. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/resume" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/skip-wait

Skip the current wait. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/skip-wait" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/push-now

Push now: a delay ends now, a queued action goes out at the next free slot (budgets still apply). Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/push-now" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/restart

Start the lead over from the beginning. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/restart" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/retry

Retry a failed step. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/retry" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/{id}/resume-webhook

Hand data to a lead waiting on a Wait-for-webhook step (it continues with it). Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/<id>/resume-webhook" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/enrollments/bulk

Run one operation on up to 1,000 enrollments. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/enrollments/bulk" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/workflows/{id}/waiting-leads/start

Start the campaign for everyone in its Contacts box (the manual trigger's Start): after the preflight, launching a never-launched campaign first. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/waiting-leads/start" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/enrollments/{id}/journey

A lead's journey through a campaign: each step done, current, stopped or ahead, with integration calls. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/enrollments/<id>/journey" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Events

POST /v1/events

Post a custom event about a lead (wakes Wait-until steps, fires Event Rules). Scope events:write.

curl -X POST "https://www.usekerux.com/api/v1/events" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Inbox

GET /v1/conversations

Conversations of campaign leads (newest first), on every channel: LinkedIn, email, WhatsApp and SMS (filter with `channel`). Scope inbox:read.

curl -X GET "https://www.usekerux.com/api/v1/conversations" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/conversations/{id}/messages

Messages of a conversation (oldest first, last 200). Scope inbox:read.

curl -X GET "https://www.usekerux.com/api/v1/conversations/<id>/messages" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/conversations/{id}/messages

Reply on the conversation's channel (queued; sent within the account's or number's daily limits, at most once, under the channel's sending rules: do-not-contact, STOP, consent, the lead's own hours for texts). Email takes an optional `subject` (else Re: the last one). Use Idempotency-Key. Scope inbox:write.

curl -X POST "https://www.usekerux.com/api/v1/conversations/<id>/messages" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/messages/{id}/send-now

Send a scheduled automatic answer now (status `scheduled`): it skips its reply delay and the campaign's hours, is still re-checked and within the account's limits, at most once. Scope inbox:write.

curl -X POST "https://www.usekerux.com/api/v1/messages/<id>/send-now" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/messages/{id}/cancel

Cancel a scheduled automatic answer: it is never sent and stays as the conversation's suggested reply. Scope inbox:write.

curl -X POST "https://www.usekerux.com/api/v1/messages/<id>/cancel" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/conversations/{id}

Labels, read/unread, archive. Scope inbox:write.

curl -X PATCH "https://www.usekerux.com/api/v1/conversations/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/replies

Classified replies from campaign leads, newest first (type: positive, meeting_requested, question, not_now, referral, negative, unsubscribe, out_of_office, other). Scope inbox:read.

curl -X GET "https://www.usekerux.com/api/v1/replies" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/replies/{id}

Correct a reply's type. Stored and sent again as a reply.<type> event; nothing is re-sent and no campaign action repeats. Scope inbox:write.

curl -X PATCH "https://www.usekerux.com/api/v1/replies/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/linkedin-invitations

Invitations people sent your LinkedIn accounts (newest first; pending by default). Only the accounts you connected, or every account when you are an admin and its connector left. Scope inbox:read.

curl -X GET "https://www.usekerux.com/api/v1/linkedin-invitations" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/linkedin-invitations/{id}/accept

Accept the invitation on LinkedIn (at most once; asking again answers with its state). Scope inbox:write.

curl -X POST "https://www.usekerux.com/api/v1/linkedin-invitations/<id>/accept" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/linkedin-invitations/{id}/ignore

Ignore the invitation on LinkedIn (the person isn't told; at most once). Scope inbox:write.

curl -X POST "https://www.usekerux.com/api/v1/linkedin-invitations/<id>/ignore" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Senders

GET /v1/senders

LinkedIn accounts with today's limits and usage. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/senders" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/senders/{id}

One LinkedIn account. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/senders/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/senders/{id}/pause

Pause a LinkedIn account (nothing is sent from it). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/senders/<id>/pause" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/senders/{id}/resume

Resume a LinkedIn account. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/senders/<id>/resume" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/senders/{id}

Change a LinkedIn account's name, timezone, country, working hours, pacing, daily/weekly limits or warm-up. Scope senders:write.

curl -X PATCH "https://www.usekerux.com/api/v1/senders/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/queue

The next LinkedIn actions per account with their estimated window, and accounts that can't send. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/queue" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/mailboxes

Connected email inboxes (Email steps send from them), with today's count, daily limit and the random gap between two sends. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/mailboxes" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/whatsapp-numbers

Connected WhatsApp numbers (Send WhatsApp steps send from them), with today's count and limit (a number goes up a ladder to 100 a day), new chats and their limit, warm-up and the random gap between two sends. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/whatsapp-numbers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Blocklist

GET /v1/blocklist

People, companies and email domains that are never contacted. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/blocklist" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/blocklist

Block people (LinkedIn URLs), companies or email domains (up to 5,000 at once). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/blocklist" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/blocklist/{id}

Unblock one entry. Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/blocklist/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Event Rules

GET /v1/event-rules

Event Rules at every scope. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/event-rules" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/event-rules

Create an Event Rule (when X happens, at any step, do Y). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/event-rules" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PATCH /v1/event-rules/{id}

Change a rule (a campaign's Always-on box): turn it on or off, rename it, change its event or its actions. Applies at once; its scope never changes. Scope workflows:write.

curl -X PATCH "https://www.usekerux.com/api/v1/event-rules/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/event-rules/{id}

Delete a rule. Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/event-rules/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/rule-runs

Recent rule runs. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/rule-runs" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/rule-runs/{id}/replay

Run a failed rule run again. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/rule-runs/<id>/replay" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Webhooks

GET /v1/event-types

Event types you can subscribe to (wildcards like lead.* work too). Scope webhooks:write.

curl -X GET "https://www.usekerux.com/api/v1/event-types" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/webhook-endpoints

Webhook endpoints. Scope webhooks:write.

curl -X GET "https://www.usekerux.com/api/v1/webhook-endpoints" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/webhook-endpoints

Add an endpoint. The signing secret is in this answer only (rotate it to get a new one). Scope webhooks:write.

curl -X POST "https://www.usekerux.com/api/v1/webhook-endpoints" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/webhook-endpoints/{id}

One endpoint. Scope webhooks:write.

curl -X GET "https://www.usekerux.com/api/v1/webhook-endpoints/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/webhook-endpoints/{id}

Change an endpoint (enabled=true turns a disabled one back on). Scope webhooks:write.

curl -X PATCH "https://www.usekerux.com/api/v1/webhook-endpoints/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/webhook-endpoints/{id}

Delete an endpoint. Scope webhooks:write.

curl -X DELETE "https://www.usekerux.com/api/v1/webhook-endpoints/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/webhook-endpoints/{id}/rotate-secret

New signing secret (the old one stops working at once). Scope webhooks:write.

curl -X POST "https://www.usekerux.com/api/v1/webhook-endpoints/<id>/rotate-secret" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/webhook-endpoints/{id}/test

Send a signed webhook.test event to this endpoint. Scope webhooks:write.

curl -X POST "https://www.usekerux.com/api/v1/webhook-endpoints/<id>/test" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/webhook-deliveries

Delivery log (30 days): attempts, response status and body. Scope webhooks:write.

curl -X GET "https://www.usekerux.com/api/v1/webhook-deliveries" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/webhook-deliveries/{id}/replay

Send this delivery's event again (same webhook-id). Scope webhooks:write.

curl -X POST "https://www.usekerux.com/api/v1/webhook-deliveries/<id>/replay" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Analytics

GET /v1/analytics/overview

Daily counts, totals with rates, per campaign, per account and (admins) per rep. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/overview" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/overview

A campaign's results, actions by type, its leads with where and why they wait, and suggestions. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/overview" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/traffic

Leads that left each step through each output, keyed "<node_id>:<port>" (last 24 hours, last 30 s). Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/traffic" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/campaigns

Every campaign's progress: enrolled, live, finished, blocked (and the biggest reason), steps, accounts. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/campaigns" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/live-map

Running campaigns step by step: leads here, waiting, blocked, and passed in the last 24 hours. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/live-map" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/needs-attention

Tasks (what needs a person): actions in review, unmatched or ambiguous webhook data, stuck leads by campaign and reason. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/needs-attention" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/needs-attention/leads

The stuck leads behind one Tasks group (campaign + reason + state), up to 1000. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/needs-attention/leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/ads

Leads per ad: platform > campaign > ad set > ad (or source / medium > campaign > content for UTMs), each lead counted once by its first touch, with campaign, reply, meeting and Won counts. Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/ads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/analytics/ads/leads

The leads behind one row of /analytics/ads (newest first). Scope analytics:read.

curl -X GET "https://www.usekerux.com/api/v1/analytics/ads/leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Activity

GET /v1/run-log

The run log: every engine entry, newest first (page with before = the last item's at). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/run-log" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/activity

The live activity feed, newest first (poll with after = the newest at you have); filter by campaign, step and status. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/activity" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Review

GET /v1/review-items

LinkedIn actions whose outcome is unknown and wait for a person (never retried on their own). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/review-items" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/review-items/{id}/fix-variable

A step paused for missing data: give the variable a fallback on the step (value), or take it out of the step (remove: true), for every lead; every lead paused on that step for missing data goes on. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/review-items/<id>/fix-variable" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/review-items/{id}/resolve

Resolve one: mark_sent or skip move the lead on without sending; send_again sends it once more; send_anyway sends a step paused for missing data with those values empty. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/review-items/<id>/resolve" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Imports

GET /v1/imports

The last 50 lead imports (CSV, Excel or pasted) with their counts. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/imports" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/imports/{id}

One import: status, progress, counts, and whether it can still be undone. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/imports/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/imports/{id}/undo

Undo an import (within its undo window): removes the leads it created and restores updated ones. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/imports/<id>/undo" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Workspace

GET /v1/members

The workspace's members and their roles. Scope admin.

curl -X GET "https://www.usekerux.com/api/v1/members" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workspace/business-profile

The business profile every AI feature reads (empty text until someone writes it). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workspace/business-profile" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/workspace/business-profile

Change the business profile's text (at most 3000 characters) and / or selling style; owners and admins. Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/workspace/business-profile" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workspace/lead-assignment

How new leads get an owner (off, round robin, or the teammate with the fewest open leads). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/workspace/lead-assignment" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/workspace/lead-assignment

Change how new leads get an owner; teammates must be members who can work leads (owners and admins). Every assignment is on the lead's timeline.. Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/workspace/lead-assignment" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workspace/engagement

How the engagement score is counted (points per signal, hot threshold, fading). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/workspace/engagement" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/workspace/engagement

Change the engagement score's points, hot threshold, fading or alert (owners and admins); new points count for the next signals. Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/workspace/engagement" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Troubleshooting

GET /v1/leads/{id}/explain

Why a lead waits or is stuck, in each campaign it is in: the reason in plain words, since when, the step, and the fixes (each with the API call or MCP tool that does it). Read-only. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/explain" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/workflows/{id}/explain

Why a campaign is stuck or slow: its state, where its leads wait and why (by step and reason), its accounts' limits used today and problems, and what to do next. Read-only. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workflows/<id>/explain" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Tasks

GET /v1/leads/{id}/tasks

The lead's tasks (open first, by due date). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/tasks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads/{id}/tasks

Create a task about the lead (assignee: a workspace member, or null for anyone). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/tasks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/tasks

The workspace's tasks: the key owner's (assigned to them or to nobody) or everyone's, open or done. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/tasks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/tasks/{id}

Mark a task done (or open again). Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/tasks/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Pipeline

GET /v1/pipeline

The pipeline board: every stage with its leads, how many and what they are worth. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/pipeline" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/pipeline/stages

Rename, add, remove or reorder the stages (2 to 20). A removed stage's leads show in the first one. Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/pipeline/stages" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PUT /v1/leads/{id}/stage

Move the lead to a pipeline stage (null takes it off the board) and/or set what the deal is worth. Scope leads:write.

curl -X PUT "https://www.usekerux.com/api/v1/leads/<id>/stage" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/leads/{id}/history

Everything with the lead, newest first: emails and LinkedIn messages both ways, meetings, notes, stage moves. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/history" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Integrations

GET /v1/integrations/lead-form-relay/{provider}

The workspace's secret URL for ad lead forms sent by Zapier or Make, and what came through it. Scope admin.

curl -X GET "https://www.usekerux.com/api/v1/integrations/lead-form-relay/<provider>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/integrations/lead-form-relay/{provider}

Make the secret URL, or a new one (the old one stops working at once); owners and admins. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/integrations/lead-form-relay/<provider>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/integrations/lead-form-relay/{provider}

Turn the secret URL off (campaign triggers stay); owners and admins. Scope admin.

curl -X DELETE "https://www.usekerux.com/api/v1/integrations/lead-form-relay/<provider>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/integrations/form-tools

Form tools that can send submissions straight to Kerux (Typeform, Tally, Jotform, Webflow...). Scope admin.

curl -X GET "https://www.usekerux.com/api/v1/integrations/form-tools" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/integrations/form-relays

The workspace's form URLs (one or more per form tool) and what came through each. Scope admin.

curl -X GET "https://www.usekerux.com/api/v1/integrations/form-relays" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/integrations/form-relays

Make a new secret URL for a form tool; owners and admins. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/integrations/form-relays" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/integrations/form-relays/{id}

One form URL, the fields of its last submission and where each goes. Scope admin.

curl -X GET "https://www.usekerux.com/api/v1/integrations/form-relays/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/integrations/form-relays/{id}

Rename a form URL or set where fields go (mapping: field name -> target, "ignore", or "auto" to clear). Scope admin.

curl -X PATCH "https://www.usekerux.com/api/v1/integrations/form-relays/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/integrations/form-relays/{id}/rotate

Make a new secret URL (the old one stops working at once); name and mapping stay. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/integrations/form-relays/<id>/rotate" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/integrations/form-relays/{id}/test

Read the tool's sample submission with this URL's mapping (nothing is stored, no lead is made). Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/integrations/form-relays/<id>/test" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/integrations/form-relays/{id}

Turn a form URL off for good; owners and admins. Scope admin.

curl -X DELETE "https://www.usekerux.com/api/v1/integrations/form-relays/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Email templates

GET /v1/email-templates

List email templates (alphabetical; without their content). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/email-templates" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/email-templates

Create an email template (names are unique in the workspace). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/email-templates" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/email-templates/{id}

One email template with its design, HTML and plain text. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/email-templates/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/email-templates/{id}

Change an email template (a new version); steps linked to it send the new version. Scope workflows:write.

curl -X PATCH "https://www.usekerux.com/api/v1/email-templates/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/email-templates/{id}

Delete an email template (steps linked to it send the copy they took when it was picked). Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/email-templates/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/email-templates/{id}/duplicate

Copy an email template under a new name. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/email-templates/<id>/duplicate" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/email-templates/{id}/versions

Earlier versions of an email template, newest first (the last 50). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/email-templates/<id>/versions" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/email-templates/{id}/versions/{version}/restore

Bring back an earlier version (saved as a new version). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/email-templates/<id>/versions/<version>/restore" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/email-images

Upload a picture for emails (PNG, JPG, GIF or WebP, up to 1 MB; 25 MB per workspace); returns its public address. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/email-images" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/email-images

The workspace's uploaded email pictures (newest first) and the space they use. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/email-images" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

DELETE /v1/email-images/{id}

Delete an uploaded email picture (emails already sent with it show it broken). Scope workflows:write.

curl -X DELETE "https://www.usekerux.com/api/v1/email-images/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Meetings

GET /v1/meetings

Meetings booked by leads (connected calendars and booking tools), newest first. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/meetings" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/possible-meetings

Meetings whose attendee might be a lead (no exact email, or the email is on several leads): confirm who it is, or say it isn't a lead. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/possible-meetings" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/possible-meetings/{id}/confirm

It's this lead: the attendee's email is learned as theirs (their next booking matches for sure) and the meeting counts as booked (the campaign's Always-on boxes run). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/possible-meetings/<id>/confirm" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/possible-meetings/{id}/reject

Not a lead: closed, nothing happens to anyone. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/possible-meetings/<id>/reject" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/mailboxes/{id}/calendar

Read this inbox's calendar for meetings booked by leads (Google / Outlook). When the account lacks the calendar permission, state is needs_permission and url is Unipile's page to grant it. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/mailboxes/<id>/calendar" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/mailboxes/{id}/calendar

Stop reading this inbox's calendar; the meetings it brought are deleted. Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/mailboxes/<id>/calendar" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/meeting-hooks

Booking tools (Calendly, Cal.com, any other) that send meetings to Kerux with their own webhook. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/meeting-hooks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/meeting-hooks

A secret URL for a booking tool's webhook (paste it in the tool). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/meeting-hooks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/meeting-hooks/{id}

Remove a booking tool's URL (and the meetings it brought). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/meeting-hooks/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/leads/{id}/calls

The lead's calls, newest first: its meetings (Google Meet / Zoom transcript state) and calls added from other tools, uploads or pasted text, with their AI summary (no text: GET /calls/{id}). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/calls" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/meetings/{id}/transcript

One meeting's transcript and summary. text: one line per turn, "[hh:mm:ss] Speaker: words" (empty until stored). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/meetings/<id>/transcript" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/calls

Add a finished call from another tool (a notetaker, a dialer...) to its lead. Fires the Kerux trigger "Call recorded" and the webhook call.recorded once, then the AI summary. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/calls" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/calls/{id}

One call (any source) with its text ("[hh:mm:ss] Speaker: words" lines), its leads and its summary. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/calls/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/unmatched-calls

Calls from other tools whose lead isn't sure (several leads have that address), newest first. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/unmatched-calls" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/calls/{id}/assign

Say which lead an unmatched call was with: it goes to the lead (Call recorded, then the summary). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/calls/<id>/assign" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/calls/uploads

Start uploading a call recording (audio or video) for a lead to transcribe it on the server; then send its parts (PUT /calls/{id}/parts/{n}, 3,000,000 bytes each). Kerux transcribes it and deletes the audio. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/calls/uploads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PUT /v1/calls/{id}/parts/{n}

One part of a call recording (n from 0), base64. The last part hands the recording to transcription. Scope leads:write.

curl -X PUT "https://www.usekerux.com/api/v1/calls/<id>/parts/<n>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/call-drafts/{id}

Approve (optionally edited) or decline an AI-written follow-up held for approval (the step "Draft the follow-up with AI"); id = the step's action id from the lead's journey. Scope enrollments:write.

curl -X POST "https://www.usekerux.com/api/v1/call-drafts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/call-hooks

Call intake URLs: secret URLs another tool (or Zapier, Make...) posts finished calls to. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/call-hooks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/call-hooks

A new call intake URL (name = the tool, shown on the lead when it sends no name). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/call-hooks" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/call-hooks/{id}

Remove a call intake URL (the calls it brought stay on their leads). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/call-hooks/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/zoom-connections

Zoom accounts connected for call transcripts (Meetings > Connected calendars). Connecting needs a person on Zoom's screen (app only). Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/zoom-connections" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

DELETE /v1/zoom-connections/{id}

Disconnect a Zoom account: Kerux's access is taken back at Zoom; transcripts already stored stay. Only its teammate, or an owner / admin. Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/zoom-connections/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/connected-calendars/{id}/meet-transcripts/off

Stop importing Google Meet transcripts with this Google Calendar (turning it on needs Google's screen: app only). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/connected-calendars/<id>/meet-transcripts/off" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Booking

GET /v1/booking-links

Booking links: public pages where people book a time on a teammate's calendar. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/booking-links" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/booking-links

Create a booking link (its page is /b/{slug}). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/booking-links" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/booking-links/{id}

One booking link. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/booking-links/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/booking-links/{id}

Change a booking link (only the fields sent). Bookings already made keep their time. Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/booking-links/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/booking-links/{id}

Remove a booking link: its page closes; bookings already made stay on the calendar. Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/booking-links/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/booking-links/{id}/availability

Free times of a booking link between two instants (at most 31 days): working hours minus the calendar's busy times, buffers and existing bookings. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/booking-links/<id>/availability" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/bookings

Bookings made on the workspace's booking links (with from: oldest first; else newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/bookings" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/bookings/{id}/cancel

Cancel a booking: the calendar event is cancelled once, the meeting is marked cancelled (campaigns are not restarted), the visitor gets an email. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/bookings/<id>/cancel" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/bookings/{id}/review

Settle a booking waiting for a person: check (read the calendar again; found = done) or release (the event isn't on the calendar: the time is free again, nothing is written). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/bookings/<id>/review" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/availability

A teammate's availability (the API key's person when user_id is left out): weekly hours, timezone, days off. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/availability" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/availability

Replace a teammate's availability (your own, or anyone's for owners and admins). Booking pages that use it change at once; bookings already made keep their time. Scope leads:write.

curl -X PUT "https://www.usekerux.com/api/v1/availability" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/availability/team

Every teammate who can take meetings, with their availability (for round robin pages). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/availability/team" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/connected-calendars

Connected Google / Outlook calendars: whether each is on, and which booking links check it for conflicts and write new meetings to it. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/connected-calendars" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

DELETE /v1/connected-calendars/{id}

Disconnect a Google Calendar connected directly (provider google): Kerux's access is taken back at Google, the meetings it brought are forgotten, bookings already made stay. Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/connected-calendars/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

SMS

GET /v1/sms

Text messages (SMS): the connected Twilio account, its numbers (Send SMS steps send from them) and the reply URL. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/sms" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/sms/twilio

Connect your own Twilio account (or replace its keys): Account SID plus the Auth Token, or an API Key SID and secret. Texts are paid to Twilio by you; Kerux reads the account's numbers. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms/twilio" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/sms/twilio/test

Test the Twilio connection and read its phone numbers again. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/sms/twilio/test" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/sms/twilio

Disconnect Twilio: its keys and numbers leave Kerux (Send SMS steps wait until it is connected again). Scope admin.

curl -X DELETE "https://www.usekerux.com/api/v1/sms/twilio" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/sms-numbers/{id}

Change how many texts a day a number sends (1 to 1,000). Scope senders:write.

curl -X PATCH "https://www.usekerux.com/api/v1/sms-numbers/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/sms-numbers/{id}/replies-to-kerux

Send this number's incoming texts to Kerux (sets its "A message comes in" webhook in your Twilio account, replacing what was there). Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms-numbers/<id>/replies-to-kerux" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/sms-opt-outs

Phones that texted STOP (never texted again until they text START), newest first. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/sms-opt-outs" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/sms/managed

Kerux SMS (texts through Kerux, paid from prepaid credits): status, numbers, the US A2P 10DLC registration, credits and prices. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/sms/managed" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/sms/managed/activate

Activate Kerux SMS for this workspace (owners and admins). Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms/managed/activate" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/sms/managed

Deactivate Kerux SMS: its numbers are released and the registration closed (credits stay for later; no refunds). Scope admin.

curl -X DELETE "https://www.usekerux.com/api/v1/sms/managed" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/sms/managed/available-numbers

Numbers Kerux can buy for you (US or Canada; replies only come back to numbers sold here). Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/sms/managed/available-numbers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/sms/managed/numbers

Buy a number (its first month is taken from the credits; then every 30 days). Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms/managed/numbers" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/sms/managed/numbers/{id}

Release a number (gone for good; Send SMS steps using it wait). No refund. Scope admin.

curl -X DELETE "https://www.usekerux.com/api/v1/sms/managed/numbers/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/sms/managed/registration

Register for US A2P 10DLC (brand and campaign). Twilio's fees are taken from the credits at cost + 7%. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms/managed/registration" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/sms/managed/registration/resend-code

Sole proprietor: send the passcode text to the owner's mobile again (valid 24 hours). Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/sms/managed/registration/resend-code" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Voice

GET /v1/voice

Your cloned voice (for voice notes in your own voice), whether voices can be made, and voice note credits. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/voice" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/voice

Clone your OWN voice from a recording of you (1-2 minutes); one voice per person. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/voice" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/voice

Delete your cloned voice here and at the voice service (voice notes in it then wait for a new one). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/voice" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/voice/credits

Voice note credits of the workspace's organization: balance, the pack, the last movements. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/voice/credits" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/workflows/{id}/voice-preview

Listen as a lead: a Message step's voice note text for one lead, spoken in your own voice. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/workflows/<id>/voice-preview" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Social planner

GET /v1/scheduled-posts

Posts written in Kerux, on every network: coming next first, then the ones already out. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/scheduled-posts" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/scheduled-posts

Write a post and schedule it (or save it as a draft): LinkedIn (sender_id, or social_account_id of a company page), Facebook, Instagram, X, Threads, Bluesky or Mastodon (social_account_id). Kerux publishes it at its time, at most once. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/scheduled-posts" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/scheduled-posts/{id}

One scheduled post, with its reason code and its history. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/scheduled-posts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/scheduled-posts/{id}

Change a post before it goes out (draft, scheduled or failed; saving a failed one schedules it again). Send the time again (local_time, scheduled_at or publish_now) or draft: true. Scope senders:write.

curl -X PATCH "https://www.usekerux.com/api/v1/scheduled-posts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/scheduled-posts/{id}/move

Move a post (and, with post_ids, the other networks' versions of it) to another day, keeping its time of day unless time is given. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/scheduled-posts/<id>/move" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/scheduled-posts/{id}/cancel

Stop a post from going out (it stays in the list as cancelled). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/scheduled-posts/<id>/cancel" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/scheduled-posts/{id}

Remove a post that never went out (published ones stay). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/scheduled-posts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/scheduled-posts/{id}/review

Decide about a post whose answer was lost and that Kerux couldn't find on the network (reason_code OUTCOME_UNKNOWN): it is there (published, optional link), publish it again, or cancel. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/scheduled-posts/<id>/review" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/scheduled-posts/{id}/watch

Start a signal watch on a published LinkedIn post: people who react or comment become leads in a list and, if chosen, enter a campaign (asking again answers with the same watch). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/scheduled-posts/<id>/watch" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/post-series

Post campaigns (a series of posts on a timeline, e.g. a launch), newest first. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/post-series" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/post-series

Create an empty post campaign (add posts with series_id; or use POST /post-series/plan). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-series" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/post-series/plan

Plan a post campaign from a goal ("launch my new feature in 2 weeks"): drafts on days of a timeline, each written for each network. Nothing is scheduled: schedule it with POST /post-series/{id}/schedule. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-series/plan" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/post-series/{id}

One post campaign with its posts (ordered by day). Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/post-series/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/post-series/{id}

Rename a post campaign or change its first day (every post that hasn't gone out moves by the same number of days). Scope senders:write.

curl -X PATCH "https://www.usekerux.com/api/v1/post-series/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/post-series/{id}/schedule

Schedule the campaign's drafts (all, or post_ids): each is checked like a single post; the ones that can't stay drafts with the reason. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-series/<id>/schedule" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/post-series/{id}

Remove a post campaign: its posts that never went out are deleted, published ones stay. Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/post-series/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/social-accounts

Places posts can go besides LinkedIn profiles: LinkedIn company pages, Facebook Pages, Instagram, X, Threads, Bluesky and Mastodon accounts (connect Facebook, X, Threads and Mastodon in the app; Bluesky with POST /social-accounts/bluesky). Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/social-accounts" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/social-accounts/linkedin-pages

Read the LinkedIn company pages a LinkedIn account manages (one read), so posts can go out as them. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/social-accounts/linkedin-pages" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/social-accounts/bluesky

Connect a Bluesky account with its handle and an app password (Bluesky > Settings > Privacy and security > App passwords). Only the session is kept; the app password is never stored. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/social-accounts/bluesky" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/social-accounts/{id}

Remove a page or account: its posts that haven't gone out are cancelled (published ones stay). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/social-accounts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/social-media/videos

Start a video upload for posts (MP4 or MOV, 50 MB at most): answers how many parts to send to PUT /social-media/videos/{id}/parts/{index}. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/social-media/videos" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

PUT /v1/social-media/videos/{id}/parts/{index}

Send one part of a video (base64, part_bytes long except the last); the last one completes it. Scope senders:write.

curl -X PUT "https://www.usekerux.com/api/v1/social-media/videos/<id>/parts/<index>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/social-media/videos/{id}

One uploaded video (complete once every part arrived). Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/social-media/videos/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Comment automation

GET /v1/comment-automations

Comment automations on the workspace's own LinkedIn posts, with what each one did. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/comment-automations" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/comment-automations

Comment a keyword, get a DM: on one of the account's own posts, people whose comment has a keyword enter a campaign once, and Kerux can answer their comment (at most once, 20 answers a day per account, in its working hours). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/comment-automations" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/comment-automations/{id}

One comment automation. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/comment-automations/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/comment-automations/{id}

Change keywords, campaign, the automatic answer, or turn it off (answers still waiting don't go out). Scope senders:write.

curl -X PATCH "https://www.usekerux.com/api/v1/comment-automations/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/comment-automations/{id}

Remove a comment automation (its comments stay; answers still waiting don't go out). Scope senders:write.

curl -X DELETE "https://www.usekerux.com/api/v1/comment-automations/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/comment-automations/{id}/check

Read the post's comments again soon (its watch reads next; the account's daily reads and daytime still apply). Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/comment-automations/<id>/check" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/post-comments

Comments on the workspace's own posts (newest first), with the keyword, the campaign and the answer. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/post-comments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/post-comments/{id}

One comment, with its answer's history. Scope senders:read.

curl -X GET "https://www.usekerux.com/api/v1/post-comments/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/post-comments/{id}/reply

Answer a comment (plain words, no variables). Kerux's worker sends it at most once, within the account's 20 answers a day. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-comments/<id>/reply" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/post-comments/{id}/cancel-reply

Stop an answer that hasn't gone out yet. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-comments/<id>/cancel-reply" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/post-comments/{id}/review

Decide about an answer whose outcome was lost and that Kerux couldn't find under the comment (reason OUTCOME_UNKNOWN): it is there (sent), send it again, or cancel. Scope senders:write.

curl -X POST "https://www.usekerux.com/api/v1/post-comments/<id>/review" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

Sending rules

GET /v1/workspace/sending-identity

Who sends: the company name and postal address every campaign email and the first text show. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workspace/sending-identity" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/workspace/sending-identity

Set who sends (owners and admins). Email and SMS campaigns can't launch without it. Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/workspace/sending-identity" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/workspace/consent-default

Whether the contacts you add count as agreed to get texts / WhatsApp (the workspace's standing consent). Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/workspace/consent-default" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/workspace/consent-default

Turn the standing consent on or off per channel (owners and admins). Scope admin.

curl -X PUT "https://www.usekerux.com/api/v1/workspace/consent-default" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/leads/{id}/consent

The lead's consent to get texts / WhatsApp: where it came from, who recorded it, when. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/leads/<id>/consent" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads/{id}/consent

Record that the lead agreed to get texts / WhatsApp on their current phone. Send SMS / WhatsApp steps only reach leads with it. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/consent" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/leads/{id}/consent/{channel}

Withdraw the lead's consent for one channel (sms or whatsapp). Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/leads/<id>/consent/<channel>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/leads/{id}/do-not-contact

Never contact this lead again on any channel: their email, phone and LinkedIn go on the do-not-contact list and they leave every campaign. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/do-not-contact" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/leads/{id}/erase

A deletion request (GDPR art. 17): delete the lead and everything Kerux holds about them in this workspace; their email, phone and LinkedIn stay on the do-not-contact list only as one-way hashes, so no campaign contacts them again. Scope admin.

curl -X POST "https://www.usekerux.com/api/v1/leads/<id>/erase" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/suppressions

The do-not-contact list: unsubscribes, STOP texts, opt-out replies, teammates' entries and deletion requests, newest first. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/suppressions" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/suppressions

Add emails or phones (with their country code) to the do-not-contact list, for one channel or all. Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/suppressions" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/suppressions/{id}

Remove an entry people added (in Settings > Sending rules, with Do not contact or through the API); owners and admins only. Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/suppressions/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Segments

GET /v1/segments

Smart segments (saved lead filters), each with how many leads are in it now. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/segments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/segments

Save a smart segment (names are unique in the workspace). Scope leads:write.

curl -X POST "https://www.usekerux.com/api/v1/segments" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

POST /v1/segments/count

How many leads some filters match right now (before saving them). Scope leads:read.

curl -X POST "https://www.usekerux.com/api/v1/segments/count" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/segments/{id}

One smart segment. Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/segments/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PATCH /v1/segments/{id}

Rename a segment or change its filters (campaigns kept in sync follow on their next check). Scope leads:write.

curl -X PATCH "https://www.usekerux.com/api/v1/segments/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

DELETE /v1/segments/{id}

Delete a segment (never its leads). Scope leads:write.

curl -X DELETE "https://www.usekerux.com/api/v1/segments/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

GET /v1/segments/{id}/leads

The leads in a segment right now (newest first). Scope leads:read.

curl -X GET "https://www.usekerux.com/api/v1/segments/<id>/leads" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

Broadcasts

GET /v1/broadcasts

Broadcasts (one message on one channel to a segment or a list), newest first. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/broadcasts" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/broadcasts

Create a broadcast as a draft (nothing is sent until POST /broadcasts/{id}/send). Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/broadcasts" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/broadcasts/{id}

One broadcast with how many got it. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/broadcasts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

PUT /v1/broadcasts/{id}

Change a draft broadcast (422 BROADCAST_ALREADY_SENT once sent). Scope workflows:write.

curl -X PUT "https://www.usekerux.com/api/v1/broadcasts/<id>" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'

GET /v1/broadcasts/{id}/check

Preflight and forecast before sending: who it reaches and how long it takes within the limits. Scope workflows:read.

curl -X GET "https://www.usekerux.com/api/v1/broadcasts/<id>/check" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY"

POST /v1/broadcasts/{id}/send

Send it (once): everyone in its segment or list enters, now or at send_at. Scope workflows:write.

curl -X POST "https://www.usekerux.com/api/v1/broadcasts/<id>/send" \
  -H "Authorization: Bearer $SHINYFLOWS_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{ ... }'