curl --request POST \
--url https://api.zivio.net/api/v4/projects/{id}/request_bafo \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'zivio-tenant-id: <api-key>' \
--data '
{
"bid_ids": [
9,
14
],
"submission_deadline": "2026-08-15T17:00:00Z"
}
'import requests
url = "https://api.zivio.net/api/v4/projects/{id}/request_bafo"
payload = {
"bid_ids": [9, 14],
"submission_deadline": "2026-08-15T17:00:00Z"
}
headers = {
"Authorization": "Bearer <token>",
"zivio-tenant-id": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'zivio-tenant-id': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({bid_ids: [9, 14], submission_deadline: '2026-08-15T17:00:00Z'})
};
fetch('https://api.zivio.net/api/v4/projects/{id}/request_bafo', 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://api.zivio.net/api/v4/projects/{id}/request_bafo",
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([
'bid_ids' => [
9,
14
],
'submission_deadline' => '2026-08-15T17:00:00Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"zivio-tenant-id: <api-key>"
],
]);
$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://api.zivio.net/api/v4/projects/{id}/request_bafo"
payload := strings.NewReader("{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("zivio-tenant-id", "<api-key>")
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://api.zivio.net/api/v4/projects/{id}/request_bafo")
.header("Authorization", "Bearer <token>")
.header("zivio-tenant-id", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zivio.net/api/v4/projects/{id}/request_bafo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["zivio-tenant-id"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}"
response = http.request(request)
puts response.read_body{
"project_id": 123,
"project_title": "Website Redesign",
"state": "bafo",
"submission_deadline": "2026-08-15T17:00:00Z",
"bafo_proposals": [
{
"bid_id": 9,
"supplier": {
"id": 45,
"name": "Acme Consulting"
}
}
],
"eliminated_proposals": [
{
"bid_id": 11,
"supplier": {
"id": 46,
"name": "Beta Partners"
}
}
],
"changed": true,
"message": "Project 123 moved to a best-and-final-offer round"
}{
"error": "invalid_token",
"error_description": "The access token provided is expired, revoked, malformed, or invalid for other reasons"
}{
"error": "feature_disabled",
"message": "Best-and-final-offer rounds are not enabled for this tenant"
}{
"error": "bid_ids_required",
"message": "bid_ids must list the shortlisted proposals continuing into the BAFO round; every other proposal on the project will be eliminated",
"eligible_proposals": [
{
"bid_id": 9,
"supplier": {
"id": 45,
"name": "Acme Consulting"
}
}
]
}Start a best-and-final-offer (BAFO) round with the listed shortlisted proposals
Moves an open project (state new) into a BAFO round (state bafo), exactly as the web UI’s BAFO action does: the proposals listed in bid_ids — which must be shortlisted and not eliminated (use GET /bids?filter[project_id]=X&filter[shortlisted]=true) — continue into the round and their suppliers are asked to submit a best and final offer by submission_deadline; EVERY other proposal on the project is eliminated and its supplier notified, so list the survivors carefully. Requires the tenant’s BAFO feature. Read the round afterwards with GET /bids?filter[project_id]=X&filter[bafo]=true.
curl --request POST \
--url https://api.zivio.net/api/v4/projects/{id}/request_bafo \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'zivio-tenant-id: <api-key>' \
--data '
{
"bid_ids": [
9,
14
],
"submission_deadline": "2026-08-15T17:00:00Z"
}
'import requests
url = "https://api.zivio.net/api/v4/projects/{id}/request_bafo"
payload = {
"bid_ids": [9, 14],
"submission_deadline": "2026-08-15T17:00:00Z"
}
headers = {
"Authorization": "Bearer <token>",
"zivio-tenant-id": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
Authorization: 'Bearer <token>',
'zivio-tenant-id': '<api-key>',
'Content-Type': 'application/json'
},
body: JSON.stringify({bid_ids: [9, 14], submission_deadline: '2026-08-15T17:00:00Z'})
};
fetch('https://api.zivio.net/api/v4/projects/{id}/request_bafo', 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://api.zivio.net/api/v4/projects/{id}/request_bafo",
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([
'bid_ids' => [
9,
14
],
'submission_deadline' => '2026-08-15T17:00:00Z'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"zivio-tenant-id: <api-key>"
],
]);
$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://api.zivio.net/api/v4/projects/{id}/request_bafo"
payload := strings.NewReader("{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("zivio-tenant-id", "<api-key>")
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://api.zivio.net/api/v4/projects/{id}/request_bafo")
.header("Authorization", "Bearer <token>")
.header("zivio-tenant-id", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.zivio.net/api/v4/projects/{id}/request_bafo")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["zivio-tenant-id"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"bid_ids\": [\n 9,\n 14\n ],\n \"submission_deadline\": \"2026-08-15T17:00:00Z\"\n}"
response = http.request(request)
puts response.read_body{
"project_id": 123,
"project_title": "Website Redesign",
"state": "bafo",
"submission_deadline": "2026-08-15T17:00:00Z",
"bafo_proposals": [
{
"bid_id": 9,
"supplier": {
"id": 45,
"name": "Acme Consulting"
}
}
],
"eliminated_proposals": [
{
"bid_id": 11,
"supplier": {
"id": 46,
"name": "Beta Partners"
}
}
],
"changed": true,
"message": "Project 123 moved to a best-and-final-offer round"
}{
"error": "invalid_token",
"error_description": "The access token provided is expired, revoked, malformed, or invalid for other reasons"
}{
"error": "feature_disabled",
"message": "Best-and-final-offer rounds are not enabled for this tenant"
}{
"error": "bid_ids_required",
"message": "bid_ids must list the shortlisted proposals continuing into the BAFO round; every other proposal on the project will be eliminated",
"eligible_proposals": [
{
"bid_id": 9,
"supplier": {
"id": 45,
"name": "Acme Consulting"
}
}
]
}Authorizations
OAuth 2.0 client credentials. The access token from POST /oauth/token is sent as a bearer token. Request only the scopes you need.
Your Zivio organisation identifier. The regional API endpoints serve every Zivio organisation, so each request must identify yours.
Path Parameters
Project ID
Body
Response
The BAFO round after the call: who continues, who was eliminated
The response is of type object.

