Skip to content

Documentv3.0.1

Updated

Last verified

Receive Drip outcome callbacks ​

Preview contract

This guide follows the current Drip callback contract. Confirm rollout status with Dinodial before using it for a production campaign.

Drip sends a signed callback when a contact reaches a terminal outcome. This guide covers the complete integration: deploy a receiver, connect it to a process, place a rehearsal call, verify delivery, and recover callbacks that could not be delivered normally.

Prompt your AI agent

Recommended
text
Use the `dino-pong` skill to connect and verify a Drip callback receiver.
Keep the callback secret out of chat, logs, source, and durable storage.
Verify raw-body signatures before parsing and persist by dd_pulse_id.
Return success only after durable storage.
For failed deliveries, read first and acknowledge only committed outcomes.
Ask for separate approval before every process, deployment, or call mutation.
Use the Dino CLI directly
text
dino workspace current
dino workspace check
dino process failed-callbacks --help
dino process ack-failed-callbacks --help

The callback receiver must:

  • accept POST requests over HTTPS;
  • use X-Dinodial-Pulse-Process-Id only to select the registered process key;
  • verify X-Dinodial-Pulse-Signature against the unmodified request body;
  • require the signed body's process_id to match the process-ID header;
  • reject stale, future, malformed, or incorrectly signed requests;
  • store each outcome idempotently using dd_pulse_id;
  • return 2xx only after durable persistence succeeds; and
  • keep the per-process callback secret outside source control and logs.

Callback lifecycle ​

  1. You create a Drip process and receive its callback secret once.
  2. You register the process and store its secret in your receiver's secret manager.
  3. Each inserted contact supplies the receiver's callback URL.
  4. Pulse sends one signed callback when the contact becomes terminal.
  5. Your receiver verifies and persists the outcome before returning 2xx.
  6. If delivery fails, you reconcile it through the authenticated failed-callback API.

Terminal statuses include answered, busy, no-answer, DND, carrier failure, and platform failure. See Drip integration for the payload, status vocabulary, identity rules, HMAC wire contract, and reconciliation semantics.

Prepare your receiver ​

Use receiver code that your organization controls. Public documentation does not distribute a callback receiver source package. The installed dino-pong skill supplies Drip operations and recovery guidance, not receiver source.

Use these receiver components:

ComponentPurpose
HTTPS serviceAccept callbacks and verify signatures
Secret managerStore one callback secret for each process
Durable data storeKeep process registration and idempotent outcomes
Deployment operationsBuild, test, deploy, inspect, and roll back the receiver

Prerequisites ​

Prepare a receiver implementation that can preserve the unmodified request body, calculate HMAC-SHA256, compare values in constant time, and write durable state.

You also need:

  • the current dino CLI configured for the intended workspace;
  • a published agent;
  • a healthy Dino runtime;
  • an outbound transport DID;
  • a model-partner credential; and
  • explicit approval before inserting a billable contact.

Verify the CLI and workspace before making changes:

sh
dino version check
dino capabilities
dino workspace current
dino workspace check
dino account get
dino catalog vox-servers
dino catalog transport-dids
dino catalog partner-credentials

Verify the receiver implementation ​

Test these cases before deployment:

  • a valid signature and payload;
  • body tampering;
  • an incorrect process secret;
  • a stale or future timestamp;
  • malformed signature fields;
  • a process-ID mismatch;
  • duplicate delivery for one dd_pulse_id;
  • a durable-store failure; and
  • each supported terminal status.

Require all implementation-specific formatting, test, static-analysis, and production-build checks to pass.

Configure durable storage ​

Store process registration separately from callback outcomes. Keep callback secrets only in the secret manager.

For each accepted callback, store at least:

  • dd_pulse_id as the idempotency key;
  • process_id and unique_id for correlation;
  • the terminal status and complete accepted payload;
  • the signature timestamp;
  • the first acceptance time; and
  • a duplicate count or equivalent duplicate-delivery evidence.

Use separate receiver and data-store deployments for production and non-production environments.

Deploy and preflight the receiver ​

Before each deployment mutation, verify the command directory, active account, exact service, data store, and expected effect. Obtain explicit approval for that mutation.

Deploy with your approved release procedure. Record the exact HTTPS callback URL and deployed version.

Confirm that the deployed receiver rejects an unsigned callback:

sh
curl -i \
  -X POST \
  -H 'Content-Type: application/json' \
  --data '{}' \
  <CALLBACK_HTTPS_URL>

Expected status: 401 Unauthorized. The rejected request must not create a durable record.

Create the Drip process ​

Read the exact agent and infrastructure records before creating the process:

sh
dino agent get --agent-id <AGENT_GENESIS_UUID>
dino catalog vox-servers
dino catalog transport-dids
dino catalog partner-credentials

Preview the process name, region, agent, Dino runtime, transport DID, partner credential, VAD mode, timing, and retention settings for the approving operator. Then create exactly one running process:

sh
dino process create-drip \
  --agent-id <AGENT_GENESIS_UUID> \
  --name 'Callback tutorial drip' \
  --region in \
  --vox-server-id <HEALTHY_DINO_RUNTIME_UUID> \
  --transport-did-id <OUTBOUND_DID_UUID> \
  --partner-credentials-id <PARTNER_CREDENTIAL_UUID> \
  --vad-mode <VAD_MODE> \
  --lens-ttl-days <30-180> \
  --hard-close-secs <90-900> \
  --process-limit <1-255> \
  --confirm-mutation process.drip.create

Choose every value before approval. Confirm that process-limit fits the selected DID's available on-demand capacity. Idle prompts and timing come from the agent flow (lifecycleAudio.idle), not this command.

Use the agent genesis by default. Each new call then resolves the latest active version in that lineage. Supply an exact version ID only when the process must remain pinned to that version.

The response contains the process id and a one-time callbackSecret. The API key authenticates your Pulse requests. The callback secret authenticates Pulse's callback requests.

Configure the process in this order:

  1. Reserve a disabled registration for the process ID.
  2. Store callbackSecret in the receiver's approved secret manager.
  3. Map the process ID to the secret binding.
  4. Enable the registration only after the secret is available.
  5. Verify that receiver status output shows no secret value.

Never put callbackSecret in source control, shell history, screenshots, tickets, logs, or the durable data store.

Read the process back and confirm that it is running with zero contacts:

sh
dino process get --process-id <PROCESS_UUID>

Place one rehearsal call ​

Create placeholders.json using the exact placeholders declared by the published agent:

json
{
  "customer_name": "Taylor"
}

Start the receiver's approved live deployment log before inserting the contact. Keep that log open.

In a second terminal, show the approving operator the exact phone number, process ID, process-scoped unique_id, placeholders, and callback URL. Inserting a contact is billable and begins dialing immediately.

After explicit approval for this exact destination and payload, insert one contact:

sh
dino process place-call \
  --process-id <PROCESS_UUID> \
  --unique-id tutorial-contact-0001 \
  --phone +12025550123 \
  --placeholders /absolute/path/to/placeholders.json \
  --confirm-mutation process.drip.placeCall \
  --callback-url <CALLBACK_URL>

Persist the returned unique_id and dd_pulse_id. When the contact terminates, the live log must show a successful callback request without its body.

Use your receiver's authenticated operations to read the durable outcome. Verify the matching dd_pulse_id, process ID, unique ID, terminal status, signature timestamp, and duplicate-delivery evidence.

Verify that Pulse has no unacknowledged delivery failure:

sh
dino process failed-callbacks --process-id <PROCESS_UUID>

An empty failures array means Pulse accepted the receiver's 2xx response. For answered calls, obtain the signed Lens review URL with:

sh
dino process list-calls --process-id <PROCESS_UUID>

Interpret the evidence ​

EvidenceWhat it proves
Receiver log reports a successful callback requestThe deployed receiver handled a live request.
Durable storage contains the callbackThe signature and schema passed before persistence.
Duplicate evidence reports one deliveryThe receiver observed one delivery for that dd_pulse_id.
Pulse reports no failed callbacksPulse received a successful response from the receiver.

Treat deployment logs as operational evidence, not callback storage. Define log retention and redaction before production use.

Recover failed deliveries ​

Do not rely only on normal webhook delivery. Periodically read the process's failed-callback queue through the authenticated Dino CLI, apply each terminal outcome idempotently using its dd_pulse_id, and acknowledge only the entries that were durably applied.

sh
dino process failed-callbacks --process-id <PROCESS_UUID>
dino process ack-failed-callbacks \
  --process-id <PROCESS_UUID> \
  --input /absolute/path/to/applied-failure-ids.json \
  --confirm-mutation process.drip.failedCallbacks.ack

Never acknowledge an entry before committing its outcome. A crash between acknowledgement and persistence would otherwise discard the recoverable copy.

Operate and update the receiver ​

Inspect the deployed version, secret bindings, outcome totals, and Pulse recovery queue:

sh
dino process get --process-id <PROCESS_UUID>
dino process failed-callbacks --process-id <PROCESS_UUID>

Before you update the receiver:

  1. Run the implementation's complete verification suite.
  2. Validate the configured production artifact without publishing it.
  3. Show the exact target and expected effect for approval.
  4. Deploy one approved version.
  5. Repeat the unsigned-callback rejection check.
  6. Inspect the failed-callback queue during the observation period.

One receiver can support multiple concurrent processes when each process has a distinct encrypted secret binding. Keep the old binding while callbacks signed with that secret can still arrive.

Production checklist ​

  • Use dedicated receiver and database deployments for each environment.
  • Store the callback secret only in a secret manager.
  • Keep only process registration metadata in the durable data store.
  • Accept callbacks only over HTTPS.
  • Verify the exact raw body before parsing JSON.
  • Reject future and stale signatures and compare HMACs in constant time.
  • Use dd_pulse_id as the idempotency key.
  • Return 2xx only after durable persistence succeeds.
  • Never log callback bodies or secrets.
  • Monitor and reconcile the failed-callback queue independently of normal delivery.
  • Decide whether persistent request logs are required and define redaction and retention first.

For the canonical payload, status vocabulary, signing rule, process-scoped identity model, and recovery contract, return to Drip integration.

Dinodial customer documentation