#Запись
Тело запроса — JSON. Ключи объекта — коды полей справочника, те же, что
показывает /fields/.
#Завести запись
curl -X POST \
-H "Authorization: Bearer КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"title": "Новая статья", "content": "<p>Текст</p>"}' \
https://ваш-сайт.ru/api/v1/lists/4/records/<?php
$data = ['title' => 'Новая статья', 'content' => '<p>Текст</p>'];
$ch = curl_init('https://ваш-сайт.ru/api/v1/lists/4/records/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode($data, JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer КЛЮЧ',
'Content-Type: application/json',
],
]);
$answer = json_decode(curl_exec($ch), true);
curl_close($ch);
echo 'номер записи: ', $answer['id'], PHP_EOL;
if ($answer['skipped']) {
echo 'не записаны поля: ', implode(', ', $answer['skipped']), PHP_EOL;
}import requests
r = requests.post(
'https://ваш-сайт.ru/api/v1/lists/4/records/',
json={'title': 'Новая статья', 'content': '<p>Текст</p>'},
headers={'Authorization': 'Bearer КЛЮЧ'},
timeout=15,
)
answer = r.json()
print('номер записи:', answer['id'])
if answer['skipped']:
print('не записаны поля:', ', '.join(answer['skipped']))const res = await fetch('https://ваш-сайт.ru/api/v1/lists/4/records/', {
method: 'POST',
headers: {
Authorization: 'Bearer КЛЮЧ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ title: 'Новая статья', content: '<p>Текст</p>' }),
});
const answer = await res.json();
console.log('номер записи:', answer.id);
if (answer.skipped.length) console.log('не записаны поля:', answer.skipped.join(', '));{
"ok": true,
"id": 138,
"skipped": [],
"url": "https://ваш-сайт.ru/blog/novaya-statya/"
}Ответ — 201. id — номер заведённой записи.
#Адрес записи
url — тот адрес, по которому запись открывает посетитель. Он есть,
если справочник выводится страницей и у записи заполнено поле
адреса.
Если адреса нет, ключа url в ответе нет вовсе. Так бывает у
справочников, которые никакая страница не выводит, — «Заявки», «Статусы»,
«Поля форм». Пустая ссылка хуже отсутствующей: по ней нажмут и попадут
никуда.
Читайте его как необязательный: answer['url'] ?? ''.
Собрать этот адрес на своей стороне нельзя: он зависит от того, какая страница выводит справочник и что записано в поле адреса. Это знает только сайт.
Заодно при записи заводится маршрут — то, по чему сайт находит запись при заходе на её адрес. Без него запись создавалась бы, а страница по своему адресу не открывалась.
PATCH отвечает так же: если поменяли адрес, url придёт новым, а
маршрут перепишется.
#Поправить запись
curl -X PATCH \
-H "Authorization: Bearer КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"title": "Заголовок поточнее"}' \
https://ваш-сайт.ru/api/v1/lists/4/records/138/<?php
$ch = curl_init('https://ваш-сайт.ru/api/v1/lists/4/records/138/');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => json_encode(['title' => 'Заголовок поточнее'],
JSON_UNESCAPED_UNICODE),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer КЛЮЧ',
'Content-Type: application/json',
],
]);
$answer = json_decode(curl_exec($ch), true);
curl_close($ch);import requests
r = requests.patch(
'https://ваш-сайт.ru/api/v1/lists/4/records/138/',
json={'title': 'Заголовок поточнее'},
headers={'Authorization': 'Bearer КЛЮЧ'},
timeout=15,
)
print(r.json())const res = await fetch('https://ваш-сайт.ru/api/v1/lists/4/records/138/', {
method: 'PATCH',
headers: {
Authorization: 'Bearer КЛЮЧ',
'Content-Type': 'application/json',
},
body: JSON.stringify({ title: 'Заголовок поточнее' }),
});
console.log(await res.json());Правятся только присланные поля. Остальные остаются как были —
прислать всю запись целиком не нужно. PUT работает так же.
#Удалить запись
curl -X DELETE -H "Authorization: Bearer КЛЮЧ" \
https://ваш-сайт.ru/api/v1/lists/4/records/138/<?php
$ch = curl_init('https://ваш-сайт.ru/api/v1/lists/4/records/138/');
curl_setopt_array($ch, [
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer КЛЮЧ'],
]);
$answer = json_decode(curl_exec($ch), true);
curl_close($ch);import requests
r = requests.delete(
'https://ваш-сайт.ru/api/v1/lists/4/records/138/',
headers={'Authorization': 'Bearer КЛЮЧ'},
timeout=15,
)
print(r.json())const res = await fetch('https://ваш-сайт.ru/api/v1/lists/4/records/138/', {
method: 'DELETE',
headers: { Authorization: 'Bearer КЛЮЧ' },
});
console.log(await res.json());{"ok": true, "id": 138}Удаление окончательное, корзины нет.
#Картинки
Поле типа «Картинка» хранит номер файла медиатеки, а не адрес:
по нему сайт собирает <picture> с webp и мобильной версией. Внешняя
ссылка в такое поле не годится — на странице выйдет пустая рамка.
Сначала положите файл в медиатеку:
curl -X POST \
-H "Authorization: Bearer КЛЮЧ" \
-F "file=@oblozhka.png" \
https://ваш-сайт.ru/api/v1/media/<?php
$ch = curl_init('https://ваш-сайт.ru/api/v1/media/');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POSTFIELDS => ['file' => new CURLFile('oblozhka.png')],
CURLOPT_HTTPHEADER => ['Authorization: Bearer КЛЮЧ'],
]);
$answer = json_decode(curl_exec($ch), true);
curl_close($ch);
echo 'номер файла: ', $answer['id'], PHP_EOL;import requests
with open('oblozhka.png', 'rb') as f:
r = requests.post(
'https://ваш-сайт.ru/api/v1/media/',
files={'file': f},
headers={'Authorization': 'Bearer КЛЮЧ'},
timeout=60,
)
print('номер файла:', r.json()['id'])const form = new FormData();
form.append('file', new Blob([await readFile('oblozhka.png')]), 'oblozhka.png');
const res = await fetch('https://ваш-сайт.ru/api/v1/media/', {
method: 'POST',
headers: { Authorization: 'Bearer КЛЮЧ' },
body: form,
});
const { id } = await res.json();{
"ok": true,
"id": 42,
"name": "oblozhka.png",
"url": "/uploads/oblozhka.png",
"files": [{"id": 42, "name": "oblozhka.png", "url": "/uploads/oblozhka.png"}]
}Полученный id и кладите в поле картинки:
curl -X PATCH \
-H "Authorization: Bearer КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"cover": "42"}' \
https://ваш-сайт.ru/api/v1/lists/4/records/138/#Файл уже лежит в uploads
Так бывает, когда файлы положили мимо панели — по SFTP или восстановлением из копии. Загружать их заново не нужно, достаточно завести в медиатеке:
curl -X POST \
-H "Authorization: Bearer КЛЮЧ" \
-H "Content-Type: application/json" \
-d '{"path": "/uploads/blog-53.webp"}' \
https://ваш-сайт.ru/api/v1/media/register/{"ok": true, "id": 193, "name": "blog-53.webp",
"url": "/uploads/blog-53.webp", "existed": false}existed: true значит, что файл уже был в медиатеке и номер у него
прежний, — повторный вызов ничего не портит и второй записи не заводит.
То же и у обычной загрузки: если прислать файл, который уже лежит в медиатеке, вернётся его номер, а копия рядом не появится. Сверка идёт по содержимому, а не по имени, — прислать тот же файл под другим именем можно, и он тоже узнается.
Принимается только имя внутри uploads: путь с .. или с вложенным
каталогом отклоняется.
Файл принимается теми же правилами, что в панели: белый список
расширений (jpg, jpeg, png, gif, webp, svg, pdf, doc,
docx, xls, xlsx, zip), безопасное имя, миниатюры создаются сами.
Расширение вне списка — отказ 422.
Почему не ссылка на чужой сервер.
Картинка, оставшаяся у того, кто её прислал, делает сайт зависимым от чужого хозяйства: удалят там — в блоге появятся дыры, и владелец сайта узнает об этом последним. Файл в своей медиатеке не зависит ни от кого.
#Что происходит с лишними полями
Записываются только объявленные поля справочника. Всё прочее отбрасывается — но не молча: отброшенное перечислено в ответе.
{"ok": true, "id": 138, "skipped": ["author", "id"]}Почему отброшенное названо вслух.
Молчаливая потеря поля выглядит как поломка API, и разбираться в ней
приходится тому, кто пишет программу на другом конце. Список skipped
отвечает на вопрос «почему не сохранилось» сразу.
Отбрасывается три вида значений:
| Что | Почему |
|---|---|
id, domain | служебные: их задаёт сайт, а не тот, кто пишет |
| поля, которых нет в справочнике | писать некуда |
| массивы и объекты | поле справочника хранит строку |
Если из присланного не осталось ни одного пригодного поля, ответ —
422 и «Нечего записывать».
#Что происходит на сайте после записи
- Сбрасывается кеш страниц — изменение видно сразу.
- Объявляется событие:
api_record_created,api_record_updatedилиapi_record_deleted. Его видно в журнале событий сайта.
Запись через API не проходит проверок формы из панели.
Обязательность полей, значения по умолчанию и подстановка адреса страницы — часть панели, а не справочника. Программа, которая пишет в API, отвечает за состав данных сама.