We will be undergoing planned maintenance on Oct 7th 6:00AM UTC / Oct 7th 2:00AM ET

Inspiration

Every logistics desk knows the exception loop. The truck is late, the tracking portal says nothing, and someone spends half an hour phoning the driver, the carrier, and the receiving dock, then retyping what they heard into a chat thread nobody can audit. The facts that decide what happens next live in phone calls: where the truck is, the real arrival time, and whether the dock will still take the load. CALL-E makes those calls programmable, so we built the whole workflow around them.

What it does

  1. Intake. An operator opens a delayed-shipment incident: shipment, promised dock time, receiving cutoff, and the driver's and dock's numbers, which they must own or be authorized to call.
  2. Inspectable call plan. Before anything rings, DockSignal shows each call's goal, questions, boundaries, exact CALL-E task text, strict result schema, and idempotency key. The operator ticks an authorization box and confirms the recipients in a dialog.
  3. Concurrent CALL-E calls. The driver and the receiving dock are called at the same time. The assistant says it is an AI calling for the named organisation.
  4. Provider-backed results. Terminal webhooks are deduplicated by CALL-E-Event-Id, and DockSignal re-fetches GET /v1/calls/{call_id} with its server key before changing anything. A late webhook can be replaced by a one-click re-check, and a duplicate delivery changes nothing.
  5. Recovery card. A deterministic rules engine combines only facts from contacts who were actually reached: location, revised ETA, blocker, receiving window, next steps, and confidence. Every fact links to its call ID and evidence. Unknowns stay unknown, disagreements are marked conflicted, and vague times like "later this afternoon" are never turned into clock times.
  6. Human approval gate. If the revised ETA is after the dock's cutoff, DockSignal suggests a follow-up call asking the dock for an exception, but never places it on its own. The operator approves it in a dialog, and their name and time are stored on the call.
  7. Close-out. The dock's answer, including any window, fee, or condition, is recorded as a result, never as an agreement. The incident closes with a timestamped decision log and a downloadable Markdown summary with masked phone numbers.

How we built it

  • Next.js 15 (App Router and route handlers), React 19, TypeScript, and Tailwind v4.
  • PostgreSQL through Drizzle ORM, with SQL migrations. Unique constraints on the idempotency key, the provider call ID, and the webhook event ID make every retry safe.
  • The CALL-E Developer API is called directly from server code with Bearer auth, a stable Idempotency-Key per incident and contact, a strict recipient_result_schema with unknown enum values, correlation metadata, and a per-call webhook_url. The API key can only be sent to CALL-E's own HTTPS origin.
  • A reconciliation job (Vercel Cron, plus on-demand polling from the incident page) covers lost or late webhooks.
  • 39 automated tests run real PostgreSQL SQL in-process through PGlite. They prove idempotent dispatch across refreshes, restarts, and concurrent launches; duplicate-webhook safety; a fetched snapshot overriding a conflicting webhook body; the approval gate; and every branch of the rules engine.

Challenges we ran into

Keeping the synthesis honest. Speech is vague, so DockSignal parses only exact clock times. Two contacts can disagree, so the fact becomes conflicted instead of silently picking one. CALL-E returns structured_result: null when validation fails, so the app shows a validation failure rather than a fact. Webhooks are not signed yet, so the trust boundary is a fresh GET /v1/calls/{call_id} with the server key, never the webhook body.

Accomplishments that we're proud of

  • No mock mode ships in the app: without a valid CALL-E key, calling is blocked and no result can appear.
  • Refreshing, double-clicking, or restarting never creates a second call.
  • The call that could change a dock appointment always waits for a person.

What we learned

Strict recipient schemas with good description text and an explicit unknown value make extraction dependable. With no cancel endpoint, call waves should be small and deliberate. failure_code is not an enum, so "no answer" and "declined" have to stay unresolved rather than be guessed.

What's next for DockSignal

The carrier dispatcher as a routine third call, using the conflict handling already in place. A job queue for reconciliation at volume. A TMS webhook that opens an incident automatically when a dock appointment is missed.

Built With

  • call-e
  • nextjs
Share this project:

Updates

Submission history