curl -X PATCH 'https://verification.didit.me/v3/questionnaires/11111111-2222-3333-4444-555555555555/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"title": "Updated Customer Onboarding"}'import requests
resp = requests.patch(
f"https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/",
headers={"x-api-key": "YOUR_API_KEY"},
json={"title": "Updated Customer Onboarding"},
timeout=10,
)
resp.raise_for_status()
print(resp.json()["questionnaire_id"], resp.json()["status"])const res = await fetch(`https://verification.didit.me/v3/questionnaires/${questionnaireUuid}/`, {
method: "PATCH",
headers: {
'x-api-key': 'YOUR_API_KEY',
"Content-Type": "application/json",
},
body: JSON.stringify({ title: "Updated Customer Onboarding" }),
});
if (!res.ok) throw new Error(`Didit ${res.status}`);
const q = await res.json();
console.log(q.questionnaire_id, q.status);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Updated Customer Onboarding'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <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://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/"
payload := strings.NewReader("{\n \"title\": \"Updated Customer Onboarding\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("x-api-key", "<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.patch("https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Updated Customer Onboarding\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Updated Customer Onboarding\"\n}"
response = http.request(request)
puts response.read_body{
"questionnaire_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"description": "<string>",
"languages": [
"<string>"
],
"default_language": "<string>",
"is_active": true,
"is_simple_questionnaire": true,
"graph": {},
"sections": [
{}
],
"questionnaire_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": 123,
"status": "draft",
"published_at": "2023-11-07T05:31:56Z",
"is_editable": true
}{
"detail": "You do not have permission to perform this action."
}Update Questionnaire
Update a questionnaire. Versioning depends on the status field you send and the current state of the version: (1) no status on a published version → the published version is updated in place (same questionnaire_id, same version); (2) no status on a draft → the draft is updated and immediately published; (3) status: "published" on a published version → a NEW published version is created under the same questionnaire_group_id (new questionnaire_id, version + 1) and returned, and any existing draft in the group is deleted; (4) status: "draft" keeps a draft as a draft (autosave) but is rejected with 400 on a published version ("Cannot revert a published version to draft.").
curl -X PATCH 'https://verification.didit.me/v3/questionnaires/11111111-2222-3333-4444-555555555555/' \
-H 'x-api-key: YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"title": "Updated Customer Onboarding"}'import requests
resp = requests.patch(
f"https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/",
headers={"x-api-key": "YOUR_API_KEY"},
json={"title": "Updated Customer Onboarding"},
timeout=10,
)
resp.raise_for_status()
print(resp.json()["questionnaire_id"], resp.json()["status"])const res = await fetch(`https://verification.didit.me/v3/questionnaires/${questionnaireUuid}/`, {
method: "PATCH",
headers: {
'x-api-key': 'YOUR_API_KEY',
"Content-Type": "application/json",
},
body: JSON.stringify({ title: "Updated Customer Onboarding" }),
});
if (!res.ok) throw new Error(`Didit ${res.status}`);
const q = await res.json();
console.log(q.questionnaire_id, q.status);<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'title' => 'Updated Customer Onboarding'
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <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://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/"
payload := strings.NewReader("{\n \"title\": \"Updated Customer Onboarding\"\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("x-api-key", "<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.patch("https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"title\": \"Updated Customer Onboarding\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://verification.didit.me/v3/questionnaires/{questionnaire_uuid}/")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"title\": \"Updated Customer Onboarding\"\n}"
response = http.request(request)
puts response.read_body{
"questionnaire_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"title": "<string>",
"description": "<string>",
"languages": [
"<string>"
],
"default_language": "<string>",
"is_active": true,
"is_simple_questionnaire": true,
"graph": {},
"sections": [
{}
],
"questionnaire_group_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": 123,
"status": "draft",
"published_at": "2023-11-07T05:31:56Z",
"is_editable": true
}{
"detail": "You do not have permission to perform this action."
}PATCH for partial updates. To rename a questionnaire, send only title or description.
{
"title": "Updated Customer Onboarding"
}
form_elements array. This replaces the previous question list. Keep any existing questions you still want to show.
{
"form_elements": [
{
"id": "occupation",
"element_type": "short_text",
"label": { "en": "What is your occupation?" },
"is_required": true
},
{
"id": "source_of_funds",
"element_type": "multiple_choice",
"label": { "en": "Source of funds" },
"options": [
{ "value": "employment", "label": { "en": "Employment" } },
{ "value": "business", "label": { "en": "Business" } }
]
}
]
}
graph, branches, next, and conditional rules.
The response includes questionnaire_id. When you update a published questionnaire, the API may create a new version. Capture the returned questionnaire_id and use it in workflows instead of assuming the id in the URL is still the latest version.Authorizations
Your application's API key, from Developers -> API keys in the Business Console. The primary key has full access. A named key can be scoped: none, read or write per resource, limited to some workflows or to approved sessions, to a list of IP addresses, and to an expiry date. 401 means the key is missing, wrong, revoked or expired; 403 means the key has no access to this resource or action, or the request came from an address outside its IP list; 404 on a session route means the session is outside the key's workflows or statuses. A key without media access receives image, video and PDF URLs as null, and a key without sessions write receives session links and tokens as null. See https://docs.didit.me/console/api-keys.
Path Parameters
Per-version UUID of the questionnaire to update.
Body
Update questionnaire metadata or replace the full linear form_elements list.
Response
Questionnaire updated. The body is the latest state of the resulting version — the in-place updated version, or the newly created published version when you sent status: "published" on a published row (in that case questionnaire_id and version differ from the ones you patched). questionnaire_id in the response is the per-version UUID; use questionnaire_group_id if you need the stable group identifier.
Full questionnaire detail returned from GET, POST (create) and PATCH (update) endpoints.
Unique identifier of the questionnaire. Use this id when referencing the questionnaire from a workflow or in subsequent update/delete requests.
Graph structure with start_node and nodes map.
Questionnaire content grouped into sections (derived from the graph).
Stable identifier that groups all versions of the same questionnaire.
draft, published True when the questionnaire can still be edited in place (draft versions).