API
Бесплатный, без ключей, с ограничением частоты запросов по IP. Шифруйте на своей стороне, а мы сохраним байты.
Базовый URL
https://api.openonce.link/api/v1
/secretsСоздать секрет
Возвращает идентификатор и время истечения.
Запрос
{
"content": "ciphertext-or-plaintext",
"ttl": "1d",
"ttlSeconds": 3600,
"views": 1,
"password": null,
"notifyChannel": "webhook",
"notifyTo": "https://hooks.slack.com/services/...",
"label": "prod db password",
"kind": "text",
"fileMeta": "{\"name\":\"config.env\",\"size\":2048,\"type\":\"text/plain\"}"
}Ответ
{
"id": "8f3kQ2mVxL",
"expiresAt": "2026-08-08T12:04:11.000Z",
"views": 1,
"hasPassword": false,
"notifyOnRead": true
}/secrets/:id/metaПроверить секрет
Сообщает, жив ли ещё секрет и сколько просмотров осталось. Просмотр при этом не расходуется.
Ответ
{
"id": "8f3kQ2mVxL",
"alive": true,
"viewsLeft": 1,
"viewsTotal": 2,
"expiresAt": "2026-08-08T12:04:11.000Z",
"hasPassword": false,
"kind": "text"
}/secrets/:id/revealПоказать секрет
Расходует один просмотр и возвращает сохранённое содержимое. Это необратимо.
Запрос
{
"password": null
}Ответ
{
"content": "ciphertext-or-plaintext",
"viewsLeft": 0,
"kind": "file",
"fileMeta": "{\"name\":\"config.env\",\"size\":2048,\"type\":\"text/plain\"}"
}/secrets/:idУничтожить секрет
Удаляет секрет до того, как его кто-либо прочитает.
Ответ
{
"destroyed": true
}Отправка файлов
Укажите kind: "file" и передайте fileMeta как JSON-строку с name, size и type. Байты идут в content, как и любые другие данные — шифруйте их сами. Учтите: fileMeta хранится как есть, поэтому не помещайте секреты в имя файла.
Уведомления о сгорании
Передайте notifyChannel и notifyTo при создании секрета, и мы вызовем ваш эндпоинт в момент прочтения. Полезная нагрузка никогда не содержит сам секрет.
POST https://your-app.com/hook
X-Openonce-Event: secret.revealed
X-Openonce-Timestamp: 1786412651
X-Openonce-Signature: sha256=9f86d081884c7d65...
{
"event": "secret.revealed",
"secretId": "8f3kQ2mVxL",
"occurredAt": "2026-08-07T17:45:47.797Z",
"viewsLeft": 0,
"label": "prod db password"
}Каждый запрос несёт подпись HMAC-SHA256 по timestamp.rawBody. Сравнивайте её за постоянное время, прежде чем доверять полезной нагрузке.
const expected = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${rawBody}`)
.digest('hex');
const isValid = crypto.timingSafeEqual(
Buffer.from(signature.replace('sha256=', '')),
Buffer.from(expected),
);Командная строка
Отправьте что угодно в ссылку, не покидая терминал.
npx openonce "my api key" --ttl 1h --views 2
Ограничения частоты
Лимиты действуют на каждый IP-адрес. При превышении возвращается 429, пока окно не сбросится.
10 за 60 с30 за 60 сОшибки
Ошибки используют стандартные коды статуса с телом JSON, содержащим код ошибки и понятное человеку сообщение.
{
"statusCode": 404,
"error": "Not Found",
"code": "SECRET_NOT_FOUND",
"message": "This secret does not exist or has already been destroyed."
}CONTENT_TOO_LARGEINVALID_NOTIFICATION_TARGETPASSWORD_REQUIREDWRONG_PASSWORDSECRET_NOT_FOUNDThrottlerException