Skip to main content
POST
/
v1
/
interview-flows
Post interview flow
curl --request POST \
  --url https://app.ribbon.ai/be-api/v1/interview-flows \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '
{
  "org_name": "<string>",
  "title": "<string>",
  "questions": [
    "<string>"
  ],
  "voice_id": "11labs-Kate",
  "language": "en-US",
  "company_logo_url": null,
  "additional_info": null,
  "additional_instructions": null,
  "interview_type": "general",
  "is_video_enabled": false,
  "is_doc_upload_enabled": false,
  "redirect_url": null,
  "webhook_url": null,
  "webhook_secret_key": null,
  "intro": null,
  "outro": null,
  "team_id": null,
  "preamble_video_url": null
}
'
import requests

url = "https://app.ribbon.ai/be-api/v1/interview-flows"

payload = {
"org_name": "<string>",
"title": "<string>",
"questions": ["<string>"],
"voice_id": "11labs-Kate",
"language": "en-US",
"company_logo_url": None,
"additional_info": None,
"additional_instructions": None,
"interview_type": "general",
"is_video_enabled": False,
"is_doc_upload_enabled": False,
"redirect_url": None,
"webhook_url": None,
"webhook_secret_key": None,
"intro": None,
"outro": None,
"team_id": None,
"preamble_video_url": None
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}

response = requests.post(url, json=payload, headers=headers)

print(response.text)
const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
org_name: '<string>',
title: '<string>',
questions: ['<string>'],
voice_id: '11labs-Kate',
language: 'en-US',
company_logo_url: null,
additional_info: null,
additional_instructions: null,
interview_type: 'general',
is_video_enabled: false,
is_doc_upload_enabled: false,
redirect_url: null,
webhook_url: null,
webhook_secret_key: null,
intro: null,
outro: null,
team_id: null,
preamble_video_url: null
})
};

fetch('https://app.ribbon.ai/be-api/v1/interview-flows', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));
<?php

$curl = curl_init();

curl_setopt_array($curl, [
CURLOPT_URL => "https://app.ribbon.ai/be-api/v1/interview-flows",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'org_name' => '<string>',
'title' => '<string>',
'questions' => [
'<string>'
],
'voice_id' => '11labs-Kate',
'language' => 'en-US',
'company_logo_url' => null,
'additional_info' => null,
'additional_instructions' => null,
'interview_type' => 'general',
'is_video_enabled' => false,
'is_doc_upload_enabled' => false,
'redirect_url' => null,
'webhook_url' => null,
'webhook_secret_key' => null,
'intro' => null,
'outro' => null,
'team_id' => null,
'preamble_video_url' => null
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);

$response = curl_exec($curl);
$err = curl_error($curl);

curl_close($curl);

if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
package main

import (
"fmt"
"strings"
"net/http"
"io"
)

func main() {

url := "https://app.ribbon.ai/be-api/v1/interview-flows"

payload := strings.NewReader("{\n \"org_name\": \"<string>\",\n \"title\": \"<string>\",\n \"questions\": [\n \"<string>\"\n ],\n \"voice_id\": \"11labs-Kate\",\n \"language\": \"en-US\",\n \"company_logo_url\": null,\n \"additional_info\": null,\n \"additional_instructions\": null,\n \"interview_type\": \"general\",\n \"is_video_enabled\": false,\n \"is_doc_upload_enabled\": false,\n \"redirect_url\": null,\n \"webhook_url\": null,\n \"webhook_secret_key\": null,\n \"intro\": null,\n \"outro\": null,\n \"team_id\": null,\n \"preamble_video_url\": null\n}")

req, _ := http.NewRequest("POST", url, payload)

req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")

res, _ := http.DefaultClient.Do(req)

defer res.Body.Close()
body, _ := io.ReadAll(res.Body)

fmt.Println(string(body))

}
HttpResponse<String> response = Unirest.post("https://app.ribbon.ai/be-api/v1/interview-flows")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"org_name\": \"<string>\",\n \"title\": \"<string>\",\n \"questions\": [\n \"<string>\"\n ],\n \"voice_id\": \"11labs-Kate\",\n \"language\": \"en-US\",\n \"company_logo_url\": null,\n \"additional_info\": null,\n \"additional_instructions\": null,\n \"interview_type\": \"general\",\n \"is_video_enabled\": false,\n \"is_doc_upload_enabled\": false,\n \"redirect_url\": null,\n \"webhook_url\": null,\n \"webhook_secret_key\": null,\n \"intro\": null,\n \"outro\": null,\n \"team_id\": null,\n \"preamble_video_url\": null\n}")
.asString();
require 'uri'
require 'net/http'

url = URI("https://app.ribbon.ai/be-api/v1/interview-flows")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"org_name\": \"<string>\",\n \"title\": \"<string>\",\n \"questions\": [\n \"<string>\"\n ],\n \"voice_id\": \"11labs-Kate\",\n \"language\": \"en-US\",\n \"company_logo_url\": null,\n \"additional_info\": null,\n \"additional_instructions\": null,\n \"interview_type\": \"general\",\n \"is_video_enabled\": false,\n \"is_doc_upload_enabled\": false,\n \"redirect_url\": null,\n \"webhook_url\": null,\n \"webhook_secret_key\": null,\n \"intro\": null,\n \"outro\": null,\n \"team_id\": null,\n \"preamble_video_url\": null\n}"

response = http.request(request)
puts response.read_body
{
  "interview_flow_id": "<string>"
}
{
"message": "<string>",
"code": 123,
"status": "<string>"
}
{
"message": "<string>",
"code": 123,
"status": "<string>"
}
{
"code": 123,
"status": "<string>",
"message": "<string>",
"errors": {}
}

Authorizations

Authorization
string
header
required

Provide your API key UUID in the 'Authorization' header prefixed with 'Bearer '. Example: 'Authorization: Bearer 123e4567-e89b-12d3-a456-426614174000'

Body

application/json
org_name
string
required

The name of the organization requesting the interview.

title
string
required

The title for the interview.

questions
string[]
required

A list of questions to include in the interview. Maximum 20 questions.

voice_id
any | null
default:11labs-Kate

The voice ID to be used for the interview agent.

Available options:
11labs-Anna,
openai-Onyx,
openai-Shimmer,
11labs-Anthony,
11labs-Kate,
11labs-Amy,
11labs-Rahul,
IPgYtHTNLjC7Bq7IPHrm,
UOIqAnmS11Reiei1Ytkc,
vUmLiNBm6MDcy1NUHaVr,
bhJUNIXWQQ94l8eI2VUf,
b3jcIbyC3BSnaRu8avEk,
xF681s0UeE04gsf0mVsJ,
uNsWM1StCcpydKYOjKyu,
BGEU6wFi2uNm6Kje1Yhk,
4kCDY3HJwvO7Zp3con83,
null
language
any | null
default:en-US

The language of the interview flow.

Available options:
en-US,
de-DE,
es-419,
hi-IN,
ja-JP,
pt-BR,
fr-FR,
zh-CN,
ko-KR,
vi-VN,
th-TH,
ar-AE,
no-NO,
null
company_logo_url
string | null

Optional URL for the company's logo. If not provided, the Ribbon logo will be shown.

additional_info
string | null

Extra contextual information relevant to the interview. This can include background details, facts, or data points that the AI may use to enrich its questions or answers. For example: research focus, demographics or situational context.

additional_instructions
string | null

Guidelines on how the AI should behave during the interview. For example, adjust tone formality, avoid certain topics, or follow specific communication rules.

interview_type
enum<string> | null
default:general

The type of interview.

Available options:
recruitment,
general,
null
is_video_enabled
boolean | null
default:false

Whether the interview is video recorded or not.

is_doc_upload_enabled
boolean | null
default:false

Whether candidates can add resumes or other documents during the interview or not.

redirect_url
string | null

The URL where interviewee will be redirected after completing the interview. Make sure you're using the full URL, including https://

webhook_url
string | null

The URL that will be called after interview processing is complete. The payload will contain interview_flow_id, interview_id, and status.

webhook_secret_key
string | null

A secret key used to sign webhook payloads. When set, an X-Ribbon-Signature header containing an HMAC-SHA256 signature will be included with each webhook request.

intro
string | null

Introductory text spoken by the AI interviewer at the beginning of the interview.

outro
string | null

Concluding text spoken by the AI interviewer at the end of the interview.

team_id
string | null

The team ID to create the interview flow for. If not provided, defaults to the oldest team in the organization.

preamble_video_url
string | null

URL of an intro video to show candidates before the interview starts. The video will be downloaded and stored by Ribbon. Supported formats: MP4 (video/mp4), QuickTime (video/quicktime), WebM (video/webm). Maximum file size: 100 MB. The URL must be publicly accessible and served by a reasonably fast host — slow or unreliable servers may cause the request to time out. When provided, the intro video is automatically enabled for the interview flow.

Response

OK

interview_flow_id
string
required

The ID of the interview flow.