Quickstart: the API
The server takes ciphertext. Encrypting is your side of the contract.
Create a secret
Send the envelope, the public salt and the parameters. There is no field for plaintext, a key or a passphrase, by design.
curl -X POST https://api.secretpaste.com/v1/secrets \
-H 'content-type: application/json' \
-d '{
"kind": "text",
"envelope": "<base64 SPE1 envelope>",
"salt": "<base64url, 22 chars>",
"size_bytes": 128,
"expires_in": 3600,
"max_views": 1
}'What a key may do
A key holds scopes, and it does exactly those: secrets:write to create and revoke, secrets:read for your own list and timelines, receipts:read for who opened what. No key administers the account it belongs to - it cannot mint another key, read billing or change a workspace, because a leaked key that could do those is a leaked account.
With the SDK
The typed client and the crypto package do the parts that are easy to get wrong.
import { createApi } from "@secretpaste/sdk";
import { encryptText, envelopeToJson, toBase64Url } from "@secretpaste/crypto";
const api = createApi({ baseUrl: "https://api.secretpaste.com" });
const sealed = await encryptText("hunter2");
const created = await api.secrets.create({
kind: "text",
envelope: envelopeToJson(sealed.envelope),
salt: toBase64Url(sealed.salt),
size_bytes: sealed.envelope.length,
expires_in: 3600,
max_views: 1,
});
// The key joins the URL here, on this device, and nowhere else.
const url = `${created.url_base}#${toBase64Url(sealed.key)}`;