Flowmingo exposes a lightweight REST surface so you can trigger interview invitations from your ATS, CRM, or internal tooling. This section explains how to create API keys and use them to call Flowmingo's integration APIs.
1. Prerequisites
- Workspace access: You need access to Settings -> Integrations -> API Keys in the company workspace.
- Interview set and/or project ID: Keep the UUID you will target (
com_interview_set_idand/orcom_project_id). - CV file hosting (if sending CVs): Upload CVs to publicly accessible HTTPS storage (or signed URLs) that Flowmingo can fetch.
2. Request an API key
2.1 Open the API Keys panel
- Sign in at
https://team.flowmingo.ai. - Open your avatar menu -> Settings.
- Go to Integrations -> API Keys.
2.2 Create a key
- Click Create API Key.
- Provide optional Name and Description.
- (Optional, recommended) add scopes such as
invite_candidatesorcreate_set. - Click Generate.
You will receive a one-time secret with format like fl_live_abcd12345.<secret>. Copy and store it immediately. After creation, key values are masked (for example: fl_live_abcd12345.****).
2.3 Update metadata
Use Edit on an existing key to update:
namedescriptionscopesstatus
2.4 Rotate or revoke
Delete a key to revoke access immediately, then create a new key and update your integrations.
2.5 Security notes
Store API keys in a secret manager (AWS Secrets Manager, GCP Secret Manager, 1Password, etc.). Never embed keys in frontend code, logs, or version control.
3. Create interview sets through the API
Use this endpoint to programmatically provision an interview set (interview or CV set) along with its questions, requirements, and access list.
3.1 Endpoint & environments
| Environment | Settings URL | API |
|---|---|---|
| Production | https://team.flowmingo.ai |
https://apis.flowmingo.ai/company/integration/interview/set/v1 |
Method: POST. Required API key scope: create_set.
3.2 Request payload
| Field | Type | Required | Notes |
|---|---|---|---|
title |
string | Yes | Max 1024 chars. Display title for the interview set. |
set_type |
int | Optional | 1 = interview (default), 2 = CV set. |
function |
string | Optional | Max 1024 chars. Functional area / department. |
description |
string | Optional | Free-text description. |
interview_duration |
int | Optional | Duration in minutes. |
number_of_retakes |
int | Optional | Number of allowed retakes for candidates. |
priority |
int | Optional | Sort/priority weighting. |
project_id |
UUID | Optional | If provided, the interview set is attached to this project. |
iai_questions |
array | Optional | Interview questions (see 3.2.1). |
iai_requirements |
array | Optional | Evaluation requirements (see 3.2.2). |
3.2.1 iai_questions[] item
| Field | Type | Required | Notes |
|---|---|---|---|
title |
string | Optional | Max 5000 chars. |
content |
string | Optional | Max 5000 chars. The question prompt. |
cfg_question_mode_id |
int | Optional | Configured question mode (e.g. text, video). |
cfg_question_type_id |
int | Optional | Configured question type. |
cfg_prioritization_id |
int | Optional | Configured prioritization level. |
priority |
int | Optional | Order weight. |
options |
array | Optional | Choice options: { id, title, titles, content, contents, priority }. |
3.2.2 iai_requirements[] item
| Field | Type | Required | Notes |
|---|---|---|---|
title |
string | Optional | Max 5000 chars. |
content |
string | Optional | Max 5000 chars. Requirement description. |
hint |
string | Optional | Max 2000 chars. |
priority |
int | Optional | Order weight. |
3.3 Sample request
curl -X POST https://apis.flowmingo.ai/company/integration/interview/set/v1 \
-H 'Content-Type: application/json' \
-H 'X-API-Key: fl_live_abcd12345.n8G3zPNw9gWkK1Kj' \
-d '{
"title": "Senior Backend Engineer - Async Interview",
"set_type": 1,
"position": "Senior Backend Engineer",
"function": "Engineering",
"description": "Async interview for senior backend candidates.",
"interview_duration": 30,
"number_of_retakes": 1,
"project_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"iai_questions": [
{
"title": "System design",
"content": "Walk us through how you would design a rate limiter.",
"priority": 1
}
],
"iai_requirements": [
{
"title": "5+ years backend experience",
"cfg_importance_id": 2,
"priority": 1
}
]
}'
import fetch from 'node-fetch'
const response = await fetch(
'https://apis.flowmingo.ai/company/integration/interview/set/v1',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'fl_live_abcd12345.n8G3zPNw9gWkK1Kj',
},
body: JSON.stringify({
title: 'Senior Backend Engineer - Async Interview',
set_type: 1,
position: 'Senior Backend Engineer',
function: 'Engineering',
interview_duration: 30,
number_of_retakes: 1,
project_id: '019c5ea9-a792-7f0d-b671-4c3c1602094e',
iai_questions: [
{
title: 'System design',
content: 'Walk us through how you would design a rate limiter.',
priority: 1,
},
],
iai_requirements: [
{ title: '5+ years backend experience', cfg_importance_id: 2, priority: 1 },
]
}),
},
)
const data = await response.json()
console.log(data)
import requests
response = requests.post(
"https://apis.flowmingo.ai/company/integration/interview/set/v1",
headers={
"Content-Type": "application/json",
"X-API-Key": "fl_live_abcd12345.n8G3zPNw9gWkK1Kj",
},
json={
"title": "Senior Backend Engineer - Async Interview",
"set_type": 1,
"position": "Senior Backend Engineer",
"function": "Engineering",
"interview_duration": 30,
"number_of_retakes": 1,
"project_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"iai_questions": [
{
"title": "System design",
"content": "Walk us through how you would design a rate limiter.",
"priority": 1,
}
],
"iai_requirements": [
{"title": "5+ years backend experience", "cfg_importance_id": 2, "priority": 1}
]
},
)
print(response.json())
<?php
$payload = [
'title' => 'Senior Backend Engineer - Async Interview',
'set_type' => 1,
'position' => 'Senior Backend Engineer',
'function' => 'Engineering',
'interview_duration' => 30,
'number_of_retakes' => 1,
'project_id' => '019c5ea9-a792-7f0d-b671-4c3c1602094e',
'iai_questions' => [
[
'title' => 'System design',
'content' => 'Walk us through how you would design a rate limiter.',
'priority' => 1,
],
],
'iai_requirements' => [
['title' => '5+ years backend experience', 'cfg_importance_id' => 2, 'priority' => 1],
],
];
$ch = curl_init('https://apis.flowmingo.ai/company/integration/interview/set/v1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: fl_live_abcd12345.n8G3zPNw9gWkK1Kj',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]any{
"title": "Senior Backend Engineer - Async Interview",
"set_type": 1,
"position": "Senior Backend Engineer",
"function": "Engineering",
"interview_duration": 30,
"number_of_retakes": 1,
"project_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"iai_questions": []map[string]any{
{
"title": "System design",
"content": "Walk us through how you would design a rate limiter.",
"priority": 1,
},
},
"iai_requirements": []map[string]any{
{"title": "5+ years backend experience", "cfg_importance_id": 2, "priority": 1},
},
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
"POST",
"https://apis.flowmingo.ai/company/integration/interview/set/v1",
bytes.NewReader(body),
)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "fl_live_abcd12345.n8G3zPNw9gWkK1Kj")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
require 'net/http'
require 'json'
require 'uri'
uri = URI('https://apis.flowmingo.ai/company/integration/interview/set/v1')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-API-Key'] = 'fl_live_abcd12345.n8G3zPNw9gWkK1Kj'
request.body = {
title: 'Senior Backend Engineer - Async Interview',
set_type: 1,
position: 'Senior Backend Engineer',
function: 'Engineering',
interview_duration: 30,
number_of_retakes: 1,
project_id: '019c5ea9-a792-7f0d-b671-4c3c1602094e',
iai_questions: [
{
title: 'System design',
content: 'Walk us through how you would design a rate limiter.',
priority: 1
}
],
iai_requirements: [
{ title: '5+ years backend experience', cfg_importance_id: 2, priority: 1 }
]
}.to_json
response = http.request(request)
puts response.body
3.4 Sample response
The endpoint returns the created interview set wrapped in a results envelope:
{
"results": {
"id": "019c6010-2f3a-7a91-9b70-4c1a6f57c8ab",
"title": "Senior Backend Engineer - Async Interview",
"set_type": 1,
"position": "Senior Backend Engineer",
"function": "Engineering",
"interview_duration": 30,
"number_of_retakes": 1,
"com_project_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"iai_questions": [
{
"id": "019c6010-3a01-77e2-9d2c-2d4a8b41f13b",
"title": "System design",
"content": "Walk us through how you would design a rate limiter.",
"priority": 1
}
],
"iai_requirements": [
{
"id": "019c6010-3b1f-7ce9-86c4-6c0aa1c3f9d2",
"title": "5+ years backend experience",
"cfg_importance_id": 2,
"priority": 1
}
]
}
}
4. Invite candidates through the API
4.1 Endpoint & environments
| Environment | Settings URL | API |
|---|---|---|
| Production | https://team.flowmingo.ai |
https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1 |
4.2 Request payload
| Field | Type | Required | Notes |
|---|---|---|---|
com_interview_set_id |
UUID | Conditionally | Required if com_project_id is not provided. |
com_project_id |
UUID | Conditionally | Required if com_interview_set_id is not provided. |
com_job_post_id |
UUID | Optional | If omitted while com_project_id is provided, the latest job post in that project is selected. |
candidates |
array | Yes | Must contain at least 1 candidate. |
candidates[].ats_candidate_id |
UUID | Optional | Must be unique within a single request. |
candidates[].email |
string | Optional | Required for invite creation; if missing and cv_link exists, the request queues candidate-entry CV processing instead. |
candidates[].name |
string | Optional | Candidate display name. |
candidates[].firstname |
string | Optional | Candidate first name override. |
candidates[].lastname |
string | Optional | Candidate last name override. |
candidates[].cv_link |
string URL | Optional | CV source URL for evaluation workflows. |
invitation_message |
string (>=10 chars) | Optional | Custom message content. |
send_invite |
boolean | Optional (default true) |
When true, invitation records are created for interview-set flows. |
4.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: fl_live_abcd12345.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
}'
import fetch from 'node-fetch'
const response = await fetch(
'https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': 'fl_live_abcd12345.n8G3zPNw9gWkK1Kj',
},
body: JSON.stringify({
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,
}),
},
)
const data = await response.json()
console.log(data)
import requests
response = requests.post(
"https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1",
headers={
"Content-Type": "application/json",
"X-API-Key": "fl_live_abcd12345.n8G3zPNw9gWkK1Kj",
},
json={
"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,
},
)
print(response.json())
<?php
$payload = [
'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,
];
$ch = curl_init('https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'X-API-Key: fl_live_abcd12345.n8G3zPNw9gWkK1Kj',
],
CURLOPT_POSTFIELDS => json_encode($payload),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
)
func main() {
payload := map[string]any{
"com_interview_set_id": "019c5ea9-a792-7f0d-b671-4c3c1602094e",
"candidates": []map[string]any{
{
"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,
}
body, _ := json.Marshal(payload)
req, _ := http.NewRequest(
"POST",
"https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1",
bytes.NewReader(body),
)
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-API-Key", "fl_live_abcd12345.n8G3zPNw9gWkK1Kj")
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
out, _ := io.ReadAll(resp.Body)
fmt.Println(string(out))
}
require 'net/http'
require 'json'
require 'uri'
uri = URI('https://apis.flowmingo.ai/company/integration/interview/candidate/invite/v1')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['X-API-Key'] = 'fl_live_abcd12345.n8G3zPNw9gWkK1Kj'
request.body = {
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
}.to_json
response = http.request(request)
puts response.body
4.4 Sample response
The endpoint returns a response envelope with per-candidate results:
{
"results": [
{
"email_address": "alex@example.com",
"cv_link": "https://storage.googleapis.com/flowmingo-demo/cv/alex.pdf",
"invitation": {
"id": "019c5eb3-fb50-707b-9833-0862efa4b275",
"email": "alex@example.com",
"status_text": "pending"
},
"submission": {
"id": "019c5eb4-55ab-76fc-90ec-98930c56a7bd",
"status_text": "need_interview"
}
}
]
}
Error details are returned per candidate in fields such as error_message, invitation_error_message, application_error_message, submission_error_message, and candidate_entry_error_message.
5. Troubleshooting
- 401 / 403: API key is missing, malformed, deleted, inactive, expired, or (when scopes are configured) missing the required scope (
invite_candidatesfor invites,create_setfor set creation). - 404 project/interview set: The UUID is invalid for your organization or the record is deleted.
- Validation errors (invite): Ensure
candidatesis non-empty and each candidate has enough data for your desired flow (invite vs CV-entry queue). - Validation errors (set):
titleis required; check max-length limits on string fields and thatproject_id(if sent) is a valid UUID owned by your organization. - Duplicate ATS IDs in one payload: Ensure
candidates[].ats_candidate_idvalues are unique per request.