Flowmingo provides two integration methods to connect your systems:
Webhooks (Outbound): Flowmingo sends real-time notifications to your endpoints when events occur (candidate email status, interview progress, evaluation results).
API Keys (Inbound): Your systems can call Flowmingo APIs to trigger actions like inviting candidates to interviews.
This guide explains how to configure webhook endpoints, secure them with HMAC signatures, create API keys, and use them to integrate with Flowmingo's candidate invitation system.
Flowmingo emits notifications whenever candidates move through invitation, interview, or evaluation workflows. This section explains how to create webhook endpoints, secure them with HMAC signatures, and understand the payloads you will receive so downstream systems (ATS, HRIS, Slack bots, etc.) stay in sync.
1. Create a webhook endpoint
Beta Setup Process:
Since the webhook UI is not yet available, please provide the Flowmingo team with the following information:
- Your webhook endpoint URL: Must be a publicly accessible HTTPS endpoint you control (e.g.,
https://your-app.com/api/flowmingo-webhook). - Events to subscribe: Specify which event types this endpoint should receive (see Supported Events below), or request "all events" to receive everything.
- Description (optional): A label to help you identify this endpoint later (e.g., "ATS sync endpoint").
The Flowmingo team will:
- Create the webhook endpoint for you
- Return your webhook signing secret (format:
whsec_...) - Configure the event subscriptions
Store the secret securely - you'll need it to verify incoming webhook signatures. Never commit it to version control or log it.
Managing endpoints:
Contact the Flowmingo team to update, delete, or regenerate secrets for your webhook endpoints. The team can also send test events to help you verify your integration.
2. Supported events
| Event | Description | Typical trigger |
|---|---|---|
invitation.status.update |
Interview invitation lifecycle updates (accepted, delivered, opened, clicked, failed). | Notification service after Flowmingo sends interview invitations. |
interview.status.update |
Candidate starts/completes an interview. | Candidate interview emits state changes. |
interview.evaluation.update |
New CV/interview/holistic evaluation results are stored. | Evaluation processor finishes scoring. |
Subscribing to a parent event (e.g., invitation.status.update) receives all sub-events of that type. You can also subscribe to specific sub-events only (e.g., invitation.status.update.invitation_email_failed).
3. Payload structure
Flowmingo wraps every event in a consistent envelope:
{
"event_id": "3a74fa26-4b66-4534-ba76-073548c95239",
"event_name": "invitation.status.update",
"payload": {
"...invitation_email_delivered..."
}
}
Content-Type is always application/json. Non-2xx responses are recorded and re-tried up to 3 times with ~5-minute spacing before the event is marked as ERROR in our system.
Invitation status payload
Event name: invitation.status.update
{
"interview_set_id": "019bcb66-2d6e-795a-9770-148355e51c51",
"interview_name": "Sales Assessment",
"candidate_id": "019bcb66-66d9-781e-96cc-e4a2b74c7fce",
"candidate_email": "alex@example.com",
"status": "invitation_email_delivered",
"reason": null,
"timestamp": 1732619345123
}
Possible status values:
invitation_email_accepted- Email Acceptedinvitation_email_delivered- Email Deliveredinvitation_email_opened- Email Openedinvitation_email_clicked- Link Clickedinvitation_email_failed- Email Failed
Interview status payload
Event name: interview.status.update.{status}
{
"interview_set_id": "intv_58e1",
"interview_name": "Sales Assessment",
"candidate_id": "cand_de8f",
"candidate_email": "alex@example.com",
"status": "started",
"timestamp": 1732619445123
}
Possible status values:
started- Interview Startedcompleted- Interview Completed
Interview evaluation payload
Event name: interview.evaluation.update.{evaluation_type}
{
"interview_set_id": "string",
"interview_name": "string",
"candidate_id": "string",
"candidate_email": "string",
"evaluation_type": "cv" | "interview" | "holistic",
"evaluation_score": "number",
"submission_url": "string",
"timestamp": "number"
}
Possible evaluation_type values:
cv- CV Evaluationinterview- Interview Evaluationholistic- CV + Interview Evaluation
Note:
overall_scoreis a decimal value out of 10 (e.g., 8.7 = 87%). Theevaluation_resultobject may include additional fields in the future; rely only on keys your integration needs.
4. Signature verification
Every delivery includes an X-Webhook-Signature header:
X-Webhook-Signature: t=1732619345,v1=3f2fdd0af4...
tis the UNIX timestamp (seconds).v1is an HMAC-SHA256 digest oftimestamp + '.' + body.- The secret is the exact
whsec_...string Flowmingo returned (do not strip the prefix; if you prefer to store only the hex portion, reattachwhsec_before use).
Example middleware (Node.js/Express) that validates the signature using the raw request body:
import crypto from 'crypto';
const WEBHOOK_SECRET = process.env.FLOWMINGO_WEBHOOK_SECRET!;
function verifySignature(rawBody: Buffer, header: string | string[] | undefined) {
if (!header || Array.isArray(header)) return false;
const parts = header.split(',');
const timestamp = parts.find((p) => p.startsWith('t='))?.split('=')[1];
const signature = parts.find((p) => p.startsWith('v1='))?.split('=')[1];
if (!timestamp || !signature) return false;
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody.toString('utf8')}`)
.digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature, 'hex'), Buffer.from(expected, 'hex'));
}
Reject requests whose timestamp is too old or whose signature comparison fails.
Flowmingo exposes a lightweight REST surface so you can trigger interview invitations from your ATS, CRM, or internal tooling. This section explains how to request API keys and use them to call Flowmingo's integration APIs.
1. Prerequisites
- Interview set ID: You'll need the UUID of the interview set you want to invite candidates to. Contact the Flowmingo team to get your interview set ID.
- CV file hosting (if sending CVs): Upload CV files to publicly accessible HTTPS storage (AWS S3, Google Cloud Storage, etc.) or generate signed URLs. Flowmingo must be able to fetch the CV from the URL you provide.
2. Request an API key
Beta Setup Process:
Since the API key UI is not yet available, please provide the Flowmingo team with the following information:
- Name: A label for this API key (e.g., "Production ATS Integration")
- Description (optional): Help remember where this key is used (e.g., "API key for Greenhouse integration")
- Interview set ID(s): Which interview set you want to invite candidates to
- Scope needed:
candidate.invite- Send interview invitations via API
The Flowmingo team will:
- Create the API key for you
- Return your API key (format:
fl_live_abcd1234.n8G3zPNw9gWkK1Kj) - Configure the scopes
Store the API key securely in your vault/secret manager (AWS Secrets Manager, GCP Secret Manager, 1Password, etc.). Never embed it in client-side code, log it, or check it into version control.
Managing API keys:
Contact the Flowmingo team to update metadata, rotate (delete and create new), or revoke your API keys.
3. Invite candidates through the API
3.1 Endpoint & environments
| Environment | Settings URL | API |
|---|---|---|
| Production | https://team.flowmingo.ai |
https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1 |
3.2 Request payload
| Field | Type | Required | Notes |
|---|---|---|---|
com_interview_set_id |
UUID | Yes | Interview set that belongs to your workspace. |
candidates[].email |
string | Yes (unless you provide to[].id) |
Candidate email; used for dedupe and invite delivery. |
candidates[].name |
string | Optional | Appears inside the invite email and dashboard. |
candidates[].cv_link |
string URL | Optional | Must be a publicly accessible HTTPS URL (e.g., from AWS S3, Google Cloud Storage, or a signed CDN URL). When present the system queues a CV-only evaluation automatically. |
invitation_message |
string (>=10 chars) | Optional | Custom message appended to the default invite template. |
send_invite |
boolean | Optional (default true) |
Set false to just enqueue candidates/CV evaluations without emailing them yet. |
3.3 Sample request
curl -X POST https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1 \
-H 'Content-Type: application/json' \
-H 'X-API-Key: flm_prod_abcd1234.n8G3zPNw9gWkK1Kj' \
-d '{
"com_interview_set_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"candidates": [
{
"name": "Alex Doe",
"email": "alex@example.com",
"cv_link": "https://storage.googleapis.com/flowmingo-demo/cv/alex.pdf"
}
],
"invitation_message": "Hi {{name}}, please complete the async interview in the next 48 hours.",
"send_invite": true
}'
3.4 Sample response
The API returns an array describing each recipient. A typical response is:
[
{
"interviewee": {
"id": "019c5eb3-fb50-707b-9833-0862efa4b275",
"comInterviewSetId": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"email": "alex@example.com",
"status": 2,
"inviteBatchId": "019c5ebc-4e63-76db-9102-56613dca107f"
},
"submission": {
"id": "019c5eb4-55ab-76fc-90ec-98930c56a7bd",
"status": 5
}
},
{
"cv_link": "https://storage.googleapis.com/flowmingo-demo/cv/no-email.pdf",
"error_message": "Queued CV for processing"
}
]
Expect error_message entries when a candidate already exists, no email/CV was provided, or when a CV-only queue is triggered without an email (the service records the batch for manual review).
3.5 Server-side behavior you get for free
The API applies multiple checks before returning:
- Confirms the interview set belongs to the calling organization and is active, preventing cross-tenant access.
- Creates a batch record and deduplicates emails/IDs before inserting.
- Reactivates existing interviewees that were inactive, or rejects exact duplicates with descriptive errors.
- Creates or links submissions to each interviewee, triggering CV-only evaluations automatically when a CV link is provided.
- Returns per-candidate status objects so you can reconcile successes vs. failures immediately.
API Key Issues
401 / 403: Usually means the API key is missing, malformed, revoked, or expired. Make sure you send
X-API-Keywith the value exactly as issued--ApiKeyGuardrejects blank/mismatched hashes (libs/commons/src/guards/api-key.guard.ts).404 interview set: The UUID either does not exist or belongs to another workspace. Confirm you copied the set ID from the same organization;
queueEmailInvitesenforces this (apps/company/src/interview/set/set.service.ts).422 validation errors: Ensure every request includes a
com_interview_set_id, at least onetoentry, and eitheremailoridper entry (apps/company/src/integration/interview/candidate/dtos/invitation.dto.ts).Rotation: Keep separate keys per system (ATS, CRM, scripts) so you can delete one without disrupting others. Document which service owns each key in the
descriptionfield.Storage: Put keys in your infrastructure secret store (AWS Secrets Manager, GCP Secret Manager, 1Password, etc.). Never log them or check them into version control.
Auditing: Because
ApiKeyGuardinjects the key ID and organization into each request (req.apiKeyAuth), Flowmingo support can trace every call. Provide the key ID (not the secret) if you open a ticket.
Webhook Issues
Signature verification failures: Ensure you're using the raw request body (not parsed JSON) when computing the HMAC signature. The timestamp must match exactly what's in the header.
Missing events: Check that your endpoint URL is correct, HTTPS, and publicly accessible. Verify the endpoint is active and subscribed to the correct event types.
Retry behavior: Non-2xx responses trigger automatic retries up to 3 times with ~5-minute spacing. Ensure your endpoint responds with a 2xx status code to acknowledge successful receipt.
Need Help?
Contact the Flowmingo team for:
- Creating or managing webhook endpoints
- Generating or rotating API keys
- Getting your interview set IDs
- Troubleshooting integration issues
- Testing your webhook or API integration
This beta integration is set up in partnership with the Flowmingo team to ensure a smooth onboarding experience.