Webhooks
How do I verify that a webhook came from HeyMilo? Webhooks created through the v2 or v4 endpoints are signed with HMAC-SHA256. The create response includes asigning_secret (it starts with whsec_). Each delivery carries an X-HeyMilo-Signature header with a timestamp and signature; recompute the signature with your secret and compare. See Verifying Webhook Signatures.
Can I retrieve or rotate a webhook’s signing secret?
No. The secret is returned once, in the create response, and never appears in get or list responses. If you lose it, delete the webhook and register a new one to get a fresh secret. Each webhook has its own secret.
I registered a webhook before signing existed. Does it have a secret?
No. Older registrations, and any created through the legacy POST /api/webhook/create endpoint, are delivered unsigned. Delete the webhook and re-create it through POST /api/v2/webhooks or POST /api/v4/webhooks to start receiving signed deliveries.
What is the webhook signing scheme?
Deliveries include X-HeyMilo-Signature (t=<unix_seconds>,v1=<hex_digest>). HeyMilo signs "{timestamp}.{raw_request_body}" with HMAC-SHA256 using your signing_secret. Verify against the raw body bytes before JSON parsing. The timestamp is part of the signed string so you can reject replays; HeyMilo doesn’t enforce a max age on its side, so pick a tolerance that fits your app (five minutes is common). Deduplicate retries using payload fields or X-HeyMilo-Delivery where it identifies a single event. Full steps and code samples: Verifying Webhook Signatures.
How should I authenticate webhook requests?
Use the signing secret and HMAC verification described in the webhook docs. That’s the supported way to confirm a delivery came from HeyMilo. If you need something beyond that (for example network-level restrictions), contact support@heymilo.ai.
When does the report_available webhook fire?
In the usual flow, events arrive in order: interview_started, then interview_completed, then report_available after AI analysis finishes. That analysis step can take from a few seconds to a few minutes after the interview is marked completed. See Event lifecycle and the report_available payload section in Webhooks.
Why is there transcript or report data but no report_available webhook (interview still in_progress)?
A common cause is the candidate ending the session before answering enough questions. Status and webhooks follow processing pipelines and completion thresholds, not who hung up. If you see partial data with in_progress and score: null, poll GET /api/v2/interviews/{id}/data or ask the candidate to resume on the same link. There is no API to manually finalize a stuck interview; contact support@heymilo.ai if you need report_available re-sent after review.
Candidates & ingestion
Can I ingest candidates through the API? Yes. The v2 API exposes candidate ingest on a posting, for examplePOST /api/v2/postings/{posting_id}/candidates (sync), async variants, and bulk routes. See v2 API Overview — Candidates & ingestion and the OpenAPI reference under v2 API Reference.
Is the Ingestion Gateway the same as the ingest API?
No. Ingestion Gateway is the in-app bulk flow (CSV and resume uploads) under Interviewer → Integrations → Inbound. Ingestion API is programmatic ingest using your API key and posting ID. Many teams use both: gateway for one-off batches, API for automation. See Inviting Candidates — Bulk ingestion.
Can I attach a resume when I ingest a candidate through the sync API?
There is no resume file field on v2 ingest. Pass a downloadable link in metadata.resume_url, or let the candidate upload in the resume step. See the next question for URL requirements.
What does metadata.resume_url require?
Use it when the posting’s first step is the resume step. HeyMilo fetches the file shortly after ingest.
- Public URL, or a pre-signed URL with the signature in the query string
- Up to 500 characters; redirects are followed
- PDF or DOCX, text-based, 10 MB or less
- No automatic retry if fetch fails — the candidate is asked to upload instead
- Keep the link available long-term; HeyMilo may read it again during evaluation and surface it on reports
Email & outreach
Can I set Reply-To on workspace, posting, template, or sender email? No. HeyMilo doesn’t expose Reply-To at those levels today. Sender Domains and Email Templates control the From address candidates see on outbound mail (after you verify your domain). They don’t route replies to your recruiters. Where do candidate replies to HeyMilo emails go? Replies to typical HeyMilo-sent candidate mail go to support@heymilo.ai, not to your team’s inboxes. If your template tells candidates to “reply to this email,” your recruiters won’t see those replies unless HeyMilo support handles them separately. Use a clear call to action you control (interview link, a mailbox you monitor) or talk to your CS Manager or support@heymilo.ai about workflow. See Sender Domains — From vs replies. After I verify my sender domain, does “via HeyMilo” disappear from the From line? Verifying your domain and sending from an address on that domain (Outreach → Sender Domains) is what makes From show your company address (for examplerecruitment@yourcompany.com) instead of a generic HeyMilo send. Some inboxes may still show a via footnote because mail is delivered through HeyMilo’s email provider; what candidates see depends on their mail app and on DKIM/SPF/DMARC alignment for your domain. Use a test send from the sender list to preview the real headers in your inbox.
Does verifying my domain change Reply-To to my verified sender?
No. Domain verification affects authenticated From addresses, not Reply-To. Replies still go to support@heymilo.ai unless product or support gives you a different workflow. See the Reply-To questions above.
Interviews & results
The transcript shows “Interviewer Sara” but I set a differentinterviewer_name. Why?
“Sara” in the transcript is a fixed display label. It isn’t read from your posting or step configuration, and the AI doesn’t use it. The AI introduces itself with the interviewer_name you set. If you rename your interviewer, update interviewer_name; the change applies to future interviews only, and past transcripts are unchanged.
Will the AI introduce itself as “Sara” if I change interviewer_name?
No. The agent uses your configured interviewer_name in the conversation. “Sara” on the transcript is only a display label on that view.
Where do per-tag typed values appear in the API? Is structured_questions the right field?
Typed per-tag values are in web_interview.tag_results[] on GET /api/v2/interviews/{id}/data. The structured_questions field holds knockout (pass/fail) results only. Both are part of the public API today. tag_results can be null when the posting has no tagged questions or extraction has not finished, so it may be missing from an early report_available webhook — fetch the interview again for the latest payload.
Can I manually finalize an interview stuck in in_progress through the API?
No. There is no finalize endpoint. Use resume links for candidates who dropped off, or contact support for edge cases.
Are recording URLs secret? How long do they work?
Some recording links are long-lived and others expire after about one hour. Treat every link as a secret. Do not store URLs long-term; fetch the interview again when you need a fresh link.
Can I read email delivery or bounce data through the API?
No. Delivery, open, click, and bounce status for HeyMilo-sent email appears in the candidate’s Activity tab in the dashboard only — not via API, export, or webhooks.
Posting configuration & Outreach API
Can I create or edit sender emails, domains, email templates, or design templates through the API? Those objects are read-only through the API today; create and edit them in the dashboard. You can attach existing sender, email template, and design template IDs to a posting via the API. What issurface_tool in web_interview step config?
A reserved internal field for interactive in-interview tasks. It cannot be set through the API and is not part of the public integration surface.