Projects API
A project is one AI interviewer with its own questions. Most other endpoints need a project ID, so this is usually the first call you make. For authentication, pagination and errors, see the API overview.
List projects#
HTTP
GET /api/v1/projectsReturns every project in the key's organization, newest first, published or not. It takes no parameters and returns all projects in one page.
Example#
curl "https://diaform.io/api/v1/projects" \
-H "Authorization: Bearer $DIAFORM_API_KEY"Response#
JSON
{
"data": [
{
"id": "b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
"name": "Onboarding interviews",
"product_name": "Acme",
"published": true,
"language": "english",
"respondent_access": "public",
"url": "https://acme.diaform.io/c/b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
"created_at": "2026-04-02T09:14:31.402057+00:00",
"published_at": "2026-04-02T09:41:05.471073+00:00"
}
],
"has_more": false,
"next_cursor": null
}Project fields#
| Field | Type | Description |
|---|---|---|
id | string | Project ID |
name | string or null | The project's name as shown in the dashboard |
product_name | string or null | Product or service name from the project's settings |
published | boolean | Whether the project is live |
language | string or null | Interview language, such as english |
respondent_access | string | public (anyone with the link) or invite_only |
url | string or null | The public conversation link. It uses your verified custom domain if you have one. |
created_at | string | When the project was created |
published_at | string or null | When it was last published |
Get a project#
HTTP
GET /api/v1/projects/{project_id}Returns one project with its current questions and conversation counts.
Example#
curl "https://diaform.io/api/v1/projects/b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d" \
-H "Authorization: Bearer $DIAFORM_API_KEY"Response#
JSON
{
"id": "b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
"name": "Onboarding interviews",
"product_name": "Acme",
"published": true,
"language": "english",
"respondent_access": "public",
"url": "https://acme.diaform.io/c/b8acb3ab-1f3d-4a7e-a846-b7f493f86b6d",
"created_at": "2026-04-02T09:14:31.402057+00:00",
"published_at": "2026-04-02T09:41:05.471073+00:00",
"questions": [
{
"id": "V1StGXR8_Z5jdHi6B-myT",
"text": "How did your first week with the product go?",
"type": "open_text",
"required": false,
"options": []
},
{
"id": "tTJUuhijB3m3nvA5horJ6",
"text": "Which plan are you on?",
"type": "single_choice",
"required": true,
"options": [
{ "id": "fvbfMZcZXZLzZWCa-jXXJ", "label": "Starter" },
{ "id": "nb-XqVVvSICqEQjZ12Mox", "label": "Pro" }
]
}
],
"conversation_counts": {
"total": 212,
"completed": 148
}
}It has every field of the list, plus:
| Field | Type | Description |
|---|---|---|
questions | array | The published questions, in order |
questions[].id | string | Question ID. Conversation summaries refer to it as question_id. |
questions[].text | string | The question as written |
questions[].type | string | open_text, single_choice, multiple_choice, nps, star_rating or file_upload |
questions[].required | boolean | Whether the question is mandatory |
questions[].options | array | Choices of a choice question, each with id and label. Empty for other types. |
conversation_counts.total | number | Conversations that were at least opened |
conversation_counts.completed | number | Conversations that reached the end |
Questions can change over time. A conversation's summary keeps the wording the respondent was actually asked.