Перейти к основному содержимому

Вакансии

POST /positions​

Возвращает список вакансий компании. Метод удобно использовать, чтобы выбрать positionId для создания интервью или синхронизировать список вакансий во внешней системе.

Запрос​

POST https://api.xeniaai.com/openapi/v1/positions
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"isArchived": false,
"limit": 50,
"offset": 0,
"sortAscending": false,
"createdFrom": "2026-01-01T00:00:00Z",
"createdTo": "2026-12-31T23:59:59Z"
}

Поля запроса​

ПолеТипПо умолчаниюОписание
isArchivedbooleannullЕсли поле не передано — без фильтра по архиву. false — только активные, true — только архивные.
limitnumber50Размер страницы. Значение нормализуется в диапазон от 10 до 200.
offsetnumber0Смещение от начала списка.
sortAscendingbooleanfalseЕсли true, сортировка от старых записей к новым.
createdFromstringnullВернуть записи, созданные не раньше указанной даты.
createdTostringnullВернуть записи, созданные не позже указанной даты.

createdFrom должен быть меньше или равен createdTo, если переданы оба поля.

Ответ​

{
"total": 1,
"limit": 50,
"offset": 0,
"items": [
{
"id": "11111111-1111-1111-1111-111111111111",
"title": "Backend Developer",
"requiredScore": 7,
"coverLetterRequired": true,
"analyticalCaseRequired": false,
"companyQuestionsAdded": true,
"candidatesTotal": 25,
"candidatesStarted": 18,
"candidatesCompleted": 12,
"createdOn": "2026-04-01T09:00:00Z",
"archivedOn": null
}
]
}

Поля вакансии в списке​

ПолеТипОписание
idguidИдентификатор вакансии.
titlestringНазвание вакансии.
requiredScorenumberМинимальная оценка для успеха.
coverLetterRequiredbooleanТребуется ли сопроводительное письмо.
analyticalCaseRequiredbooleanТребуется ли аналитический кейс.
companyQuestionsAddedbooleanДобавлены ли в вакансию вопросы о компании.
candidatesTotalnumberОбщее количество созданных интервью по вакансии.
candidatesStartednumberКоличество кандидатов, начавших интервью.
candidatesCompletednumberКоличество кандидатов, завершивших интервью.
createdOnstringДата создания вакансии.
archivedOnstring или nullДата архивации, если вакансия архивная.

GET /positions/{id}​

Возвращает подробную информацию по вакансии: настройки, статистику, вопросы, сопроводительное письмо и аналитический кейс, если они настроены.

Запрос​

GET https://api.xeniaai.com/openapi/v1/positions/11111111-1111-1111-1111-111111111111
X-API-KEY: <YOUR_API_KEY>

Ответ​

{
"id": "11111111-1111-1111-1111-111111111111",
"title": "Backend Developer",
"topics": ["C#", ".NET", "SQL"],
"requiredScore": 7,
"publicLinkActive": true,
"tags": ["middle", "remote"],
"createdOn": "2026-04-01T09:00:00Z",
"interviewStats": {
"total": 25,
"started": 18,
"completed": 12,
"archived": 3,
"averageScore": 7.4,
"averageFeedbackStars": 4.6
},
"questions": {
"total": 1,
"items": [
{
"id": "33333333-3333-3333-3333-333333333333",
"text": "Расскажите про опыт оптимизации SQL-запросов.",
"silentText": null,
"imageUrl": null,
"instruction": "Оцените практический опыт кандидата.",
"isSkippable": false,
"weight": 3,
"createdOn": "2026-04-01T09:10:00Z"
}
]
},
"coverLetter": {
"requestText": "Опишите, почему вам интересна эта роль.",
"evaluationCriteria": [
{
"name": "Мотивация",
"instruction": "Оцените релевантность мотивации кандидата.",
"type": 0,
"weight": 2,
"orderIndex": 0,
"createdOn": "2026-04-01T09:15:00Z"
}
],
"createdOn": "2026-04-01T09:15:00Z"
},
"analyticalCase": {
"caseText": "Проанализируйте падение конверсии в обучающем продукте.",
"timeInHours": 2,
"createdOn": "2026-04-01T09:20:00Z",
"questions": [
{
"orderIndex": 0,
"text": "Какие гипотезы вы проверите в первую очередь?",
"instruction": "Оцените структурность и бизнес-логику ответа.",
"weight": 3,
"createdOn": "2026-04-01T09:20:00Z"
}
]
}
}

Поля ответа​

ПолеТипОписание
idguidИдентификатор вакансии.
titlestringНазвание вакансии.
topicsstring[]Темы или направления, к которым относится вакансия.
requiredScorenumberМинимальная оценка для успеха.
publicLinkActivebooleanАктивна ли публичная ссылка на вакансию.
tagsstring[]Теги вакансии.
createdOnstringДата создания вакансии.
objectАгрегированная статистика по интервью на вакансии.
objectВопросы интервью.
object или nullНастройки сопроводительного письма. Может быть null, если сопроводительное письмо не требуется.
object или nullНастройки аналитического кейса. Может быть null, если кейс не требуется.

POST /position​

Создает вакансию в объеме шага «Детали позиции»: метаданные, условия и вопросы интервью. Сопроводительное письмо, аналитический кейс, вопросы о компании и email-шаблоны через этот метод не передаются — для них есть отдельные методы ниже. Вопросы можно передать явно в questions либо сгенерировать через generateQuestionsCount.

После успешного сохранения API сразу возвращает идентификатор вакансии и список вопросов с реальными id.

Запрос​

POST https://api.xeniaai.com/openapi/v1/position
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"title": "Backend Developer",
"topic": "backend, csharp",
"type": 0,
"requiredScore": 5,
"scoreScale": 10,
"timePerQuestion": 150,
"seniority": 1,
"language": "RU",
"reportLanguage": "RU",
"addressingFormality": 1,
"saveAudio": true,
"saveVideo": false,
"isRandomOrder": false,
"randomQuestionsCount": null,
"randomSelectionMode": 0,
"questionBlocks": [],
"tags": ["openapi"],
"aggregateByCompetencies": false,
"cheatingPolicy": null,
"questions": [
{
"id": "00000000-0000-0000-0000-000000000000",
"orderIndex": 0,
"type": 0,
"text": "Расскажите о своём опыте разработки на C#.",
"textTranslation": null,
"language": "RU",
"context": null,
"silentText": null,
"competency": null,
"isRequired": true,
"weight": 2,
"contextCardQuestionId": null,
"questionBlockId": null,
"isLinkedToContextCard": false,
"hideAfterStudy": false,
"isOptionsRandomOrder": false,
"options": []
},
{
"id": "00000000-0000-0000-0000-000000000000",
"orderIndex": 1,
"type": 1,
"text": "Какой принцип SOLID нарушает класс с десятками несвязанных обязанностей?",
"textTranslation": null,
"language": "RU",
"context": null,
"silentText": null,
"competency": null,
"isRequired": true,
"weight": 2,
"contextCardQuestionId": null,
"questionBlockId": null,
"isLinkedToContextCard": false,
"hideAfterStudy": false,
"isOptionsRandomOrder": false,
"options": [
{
"id": "00000000-0000-0000-0000-000000000000",
"text": "Single Responsibility",
"textTranslation": null,
"orderIndex": 0,
"isCorrect": true
},
{
"id": "00000000-0000-0000-0000-000000000000",
"text": "Open/Closed",
"textTranslation": null,
"orderIndex": 1,
"isCorrect": false
},
{
"id": "00000000-0000-0000-0000-000000000000",
"text": "Liskov Substitution",
"textTranslation": null,
"orderIndex": 2,
"isCorrect": false
}
]
}
]
}

Ответ​

{
"id": "11111111-1111-1111-1111-111111111111",
"questions": [
{
"id": "22222222-2222-2222-2222-222222222222",
"orderIndex": 0,
"text": "Расскажите о своём опыте разработки на C#."
},
{
"id": "33333333-3333-3333-3333-333333333333",
"orderIndex": 1,
"text": "Какой принцип SOLID нарушает класс с десятками несвязанных обязанностей?"
}
]
}

Сохраните id вопросов из ответа — они нужны для последующего PUT /positions/{id} без лишнего GET.

Поля тела запроса​

ПолеТипОписание
titlestringНазвание вакансии.
topicstringТемы/навыки вакансии, обычно через запятую.
typenumberТип позиции. См. справочник enum type (позиция).
requiredScorenumberМинимальная оценка для успеха. Должна попадать в диапазон выбранной шкалы.
scoreScalenumberШкала оценки: 3 или 10.
timePerQuestionnumberВремя на ответ на вопрос в секундах (на уровне вакансии).
senioritynumberУровень позиции. См. справочник enum seniority.
languagestringЯзык интервью, например RU.
reportLanguagestringЯзык отчета. Может совпадать с language.
addressingFormalitynumberФорма обращения. Имеет смысл при language: RU. См. справочник enum.
saveAudiobooleanСохранять ли аудио ответов кандидата.
saveVideobooleanСохранять ли видео.
isRandomOrderbooleanСлучайный порядок вопросов.
randomQuestionsCountnumberСколько вопросов выбирать случайно. Используется при режимах random selection.
randomSelectionModenumberРежим случайной выборки вопросов. См. справочник enum.
questionBlocksobject[]Блоки вопросов для режима ByBlocks. При других режимах обычно пустой массив.
tagsstring[]Теги вакансии.
potokLinkstringСвязь с вакансией Potok (если используется интеграция).
friendworkJobIdnumberID вакансии Friendwork.
huntflowJobIdnumberID вакансии Huntflow.
talantixJobIdnumberID вакансии Talantix.
estaffJobIdstringID вакансии e-Staff.
aggregateByCompetenciesbooleanЕсли true, компетенции вопросов учитываются. Если false, поле competency у вопросов при сохранении обнуляется.
cheatingPolicyobjectЛимиты на переключения вкладки. Если поле не передано, политика не задается.
generateQuestionsCountnumberЕсли задано число от 1 до 20, API генерирует столько Audio-вопросов по title/topic/seniority/языкам вакансии и игнорирует массив questions. Если поле отсутствует — используются переданные questions.
questionsobject[]Список вопросов интервью. Игнорируется при заданном generateQuestionsCount.

Автогенерация вопросов при создании​

Чтобы не передавать questions вручную, укажите generateQuestionsCount (от 1 до 20). Переданный массив questions в этом случае игнорируется.

{
"title": "C# Developer",
"topic": "C#, .NET, ASP.NET Core, SQL",
"type": 0,
"requiredScore": 5,
"scoreScale": 10,
"timePerQuestion": 150,
"seniority": 1,
"language": "RU",
"reportLanguage": "RU",
"addressingFormality": 1,
"saveAudio": true,
"saveVideo": false,
"isRandomOrder": false,
"randomQuestionsCount": null,
"randomSelectionMode": 0,
"questionBlocks": [],
"tags": ["openapi"],
"aggregateByCompetencies": false,
"cheatingPolicy": null,
"questions": [],
"generateQuestionsCount": 5
}

Формат ответа тот же, что у обычного создания: id вакансии и список сгенерированных вопросов с реальными id.

Поля вопроса​

ПолеТипОписание
idguidПри создании нового вопроса передавайте 00000000-0000-0000-0000-000000000000. Реальный id вернется в ответе.
orderIndexnumberПорядок вопроса, начиная с 0.
typenumberТип вопроса. См. справочник enum questions[].type.
textstringТекст вопроса (то, что озвучивается / показывается кандидату).
textTranslationstringПеревод текста для рекрутера, если язык отчета отличается.
languagestringЯзык вопроса, обычно совпадает с языком интервью.
contextstringИнструкция/контекст для оценки ответа.
silentTextstringТекст, который показывается кандидату, но не озвучивается.
competencystringКомпетенция. Имеет смысл при aggregateByCompetencies: true.
isRequiredbooleanОбязателен ли ответ на вопрос.
weightnumberВес вопроса: 1, 2 или 3. См. справочник enum weight.
contextCardQuestionIdguidСвязь с вопросом-карточкой контекста.
questionBlockIdguidБлок вопроса для режима ByBlocks.
isLinkedToContextCardbooleanПризнак связи с context card.
hideAfterStudybooleanДля context card: скрывать после ознакомления.
isOptionsRandomOrderbooleanДля SingleChoice: случайный порядок вариантов.
optionsobject[]Варианты ответа. Нужны для type: 1 (SingleChoice).

Отдельного поля времени на вопрос нет: используйте timePerQuestion на уровне вакансии.

Поля ответа​

ПолеТипОписание
idguidИдентификатор созданной вакансии.
questionsobject[]Сохраненные вопросы, отсортированные по orderIndex.

Если вакансию не удалось создать (например, нет активной подписки), API вернет 400 Bad Request.

PUT /positions/{id}​

Обновляет вакансию тем же контрактом, что и POST /position. Идентификатор вакансии передается в URL.

Поле generateQuestionsCount при обновлении не используется — вопросы задаются только через массив questions.

Поведение вопросов:

  • вопрос с существующим id — обновляется;
  • вопрос с id: 00000000-0000-0000-0000-000000000000 — создается;
  • вопрос есть в вакансии, но отсутствует в теле запроса — удаляется;
  • если передать questions: [], существующие вопросы не изменяются.

При aggregateByCompetencies: false значения competency в вопросах сохраняются как null (ошибка не возвращается).

Запрос​

PUT https://api.xeniaai.com/openapi/v1/positions/11111111-1111-1111-1111-111111111111
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"title": "Backend Developer (updated)",
"topic": "backend, csharp, api",
"type": 0,
"requiredScore": 6,
"scoreScale": 10,
"timePerQuestion": 180,
"seniority": 1,
"language": "RU",
"reportLanguage": "RU",
"addressingFormality": 1,
"saveAudio": true,
"saveVideo": false,
"isRandomOrder": false,
"randomQuestionsCount": null,
"randomSelectionMode": 0,
"questionBlocks": [],
"tags": ["openapi", "updated"],
"aggregateByCompetencies": false,
"cheatingPolicy": null,
"questions": [
{
"id": "22222222-2222-2222-2222-222222222222",
"orderIndex": 0,
"type": 0,
"text": "Расскажите о своём опыте разработки на C# и ASP.NET Core.",
"textTranslation": null,
"language": "RU",
"context": null,
"silentText": null,
"competency": null,
"isRequired": true,
"weight": 2,
"contextCardQuestionId": null,
"questionBlockId": null,
"isLinkedToContextCard": false,
"hideAfterStudy": false,
"isOptionsRandomOrder": false,
"options": []
},
{
"id": "00000000-0000-0000-0000-000000000000",
"orderIndex": 1,
"type": 0,
"text": "Как вы проектируете REST API?",
"textTranslation": null,
"language": "RU",
"context": null,
"silentText": null,
"competency": null,
"isRequired": true,
"weight": 2,
"contextCardQuestionId": null,
"questionBlockId": null,
"isLinkedToContextCard": false,
"hideAfterStudy": false,
"isOptionsRandomOrder": false,
"options": []
}
]
}

В примере первый вопрос обновляется (сохранен его id), второй добавляется как новый. Любые вопросы вакансии, не перечисленные в массиве, будут удалены.

Ответ​

{
"id": "11111111-1111-1111-1111-111111111111",
"questions": [
{
"id": "22222222-2222-2222-2222-222222222222",
"orderIndex": 0,
"text": "Расскажите о своём опыте разработки на C# и ASP.NET Core."
},
{
"id": "44444444-4444-4444-4444-444444444444",
"orderIndex": 1,
"text": "Как вы проектируете REST API?"
}
]
}

Формат ответа совпадает с POST /position. Если вакансия не найдена или принадлежит другой компании, API вернет 404 Not Found. При проблемах с подпиской или валидацией — 400 Bad Request.

POST /position/generate​

Создает вакансию по текстовому описанию: GPT генерирует title, topic, seniority и вопросы. Остальные параметры create задаются дефолтами API: requiredScore: 5, scoreScale: 10, timePerQuestion: 150, saveAudio: true, saveVideo: false.

Сопроводительное письмо и вопросы о компании этим методом не настраиваются — используйте отдельные PUT ниже.

Запрос​

POST https://api.xeniaai.com/openapi/v1/position/generate
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"description": "Ищем Middle C# разработчика: ASP.NET Core, EF Core, PostgreSQL, опыт микросервисов и code review.",
"skillsPercentage": 2,
"numberOfQuestions": 5,
"type": 0,
"language": "RU",
"reportLanguage": "RU",
"aggregateByCompetencies": false,
"addressingFormality": 1
}

Поля тела запроса​

ПолеТипОписание
descriptionstringОписание вакансии / требований.
skillsPercentagenumberБаланс hard/soft skills. См. справочник enum skillsPercentage. По умолчанию 2 (HardSkillsMostly).
numberOfQuestionsnumberСколько вопросов сгенерировать. Диапазон 1–20.
typenumberТип позиции. См. справочник enum type (позиция).
languagestringЯзык интервью, например RU.
reportLanguagestringЯзык отчета.
aggregateByCompetenciesbooleanГенерировать ли компетенции у вопросов.
addressingFormalitynumberФорма обращения. Имеет смысл при language: RU.

Ответ​

Формат совпадает с POST /position: id вакансии и список вопросов с id. При ошибке генерации или валидации — 400 Bad Request.

PUT /positions/{id}/company-questions​

Полностью заменяет список «вопросов о компании» у вакансии. Это не вопросы интервью: у каждого элемента есть текст вопроса и контекст/эталонный ответ (context).

Пустой массив questions: [] удаляет все вопросы о компании.

Запрос​

PUT https://api.xeniaai.com/openapi/v1/positions/11111111-1111-1111-1111-111111111111/company-questions
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"questions": [
{
"text": "Чем занимается компания?",
"context": "Кратко о продукте и рынке."
},
{
"text": "Какие ценности важны в команде?",
"context": "Открытость, ответственность, качество."
}
]
}

Поля​

ПолеТипОписание
questionsobject[]Новый полный список вопросов о компании.
questions[].textstringТекст вопроса кандидату.
questions[].contextstringКонтекст / ожидаемый ориентир для ответа.
questions[].orderIndexnumberОпционально; при сохранении порядок задается порядком элементов в массиве.

Ответ​

{
"count": 2
}

Если вакансия не найдена — 404 Not Found.

PUT /positions/{id}/cover-letter​

Включает, обновляет или отключает запрос сопроводительного письма у вакансии.

Базовый сценарий — достаточно передать requestCoverLetter: true. Если requestText и/или evaluationCriteria не заданы, API подставит дефолтные значения по языку интервью вакансии (как в кабинете Xenia AI).

Включение (минимум)​

PUT https://api.xeniaai.com/openapi/v1/positions/11111111-1111-1111-1111-111111111111/cover-letter
Content-Type: application/json
X-API-KEY: <YOUR_API_KEY>
{
"requestCoverLetter": true
}

Включение с кастомными настройками​

{
"requestCoverLetter": true,
"requestText": "Опишите, почему вам интересна эта роль.",
"evaluationCriteria": [
{
"name": "Релевантность опыта",
"instruction": "Оцените связь опыта кандидата с требованиями вакансии.",
"type": 0,
"weight": 10,
"orderIndex": 0
}
]
}

Отключение​

{
"requestCoverLetter": false
}

Поля​

ПолеТипОписание
requestCoverLetterbooleantrue — включить/обновить, false — удалить сопроводительное письмо.
requestTextstringТекст запроса кандидату. Если пустой при включении — подставляется дефолт по языку вакансии.
evaluationCriteriaobject[]Критерии оценки. Если не заданы или [] при включении — подставляются дефолтные критерии.
evaluationCriteria[].namestringНазвание критерия.
evaluationCriteria[].instructionstringИнструкция для оценки.
evaluationCriteria[].typenumberТип критерия. См. criteria.type (0 Scoring, 1 Threshold).
evaluationCriteria[].weightnumberВес критерия от 1 до 10 (не путать с весом вопросов интервью 1–3).
evaluationCriteria[].orderIndexnumberПорядок; при сохранении нормализуется по индексу в массиве.

Ответ​

При включении:

{
"requestCoverLetter": true,
"requestText": "…",
"evaluationCriteriaCount": 5
}

При отключении:

{
"requestCoverLetter": false
}

Если вакансия не найдена — 404 Not Found.