Initialize a two-step upload

Creates an upload record and returns a short-lived upload token. The client uploads the file to uploadUrl with X-Upload-Token. Used by the web UI and desktop apps.

post/v1/upload/init

Request

  • Base URL: https://api.payaion.com
  • URL: https://api.payaion.com/v1/upload/init
  • Auth: one of:
    • none
    • API key in header X-Aion-Key
    • HTTP bearer

Request body

fileNamestring required
sizeBytesinteger required
pricePerDownloadnumber nullable

Price per download in USD (e.g. 0.50). Omit or set to 0 for free downloads. Must be at least 0.000001 — anything smaller rounds to zero atomic USDC and is rejected as invalid_price. A price needs somewhere to pay: either the account's payout address or, for a keyless caller, payoutAddress below.

payoutAddressstring

Where a keyless (guest) seller's earnings go — this is what lets someone sell without an account. Honoured for guest callers only: for an account the payout address is a dashboard setting, and a value sent here by an API key is ignored so a key can never redirect that account's earnings.

retentionHours12 | 24 | 168 | 336

How long the share link lives: 12h, 24h, 7 days or 14 days. Capped by the caller's plan (guests max 14 days). Cannot be combined with a price — a buyer's access is guaranteed for 30 days, which a short link cannot honour, so the pair is rejected with retention_conflicts_with_price. Omit for the plan default.

passwordHashstring

bcrypt hash of a file password (free files only — a paid file is gated by payment). Computed by the web BFF; plaintext never reaches the gateway.

passwordHintstring

Shown to a visitor who needs the password. Max 120 characters.

encryption'e2ee'

Private Link. The file is encrypted client-side into a PAY1 container and the key never reaches Payaion; sizeBytes is then the ciphertext size and fileName is ignored (stored as "encrypted"). Cannot be combined with a price or a listing (e2ee_not_sellable, e2ee_not_listable). A passwordHash is allowed and recommended for sensitive files. The client MUST then also derive the file key from the link key and the password (PAY1 header flag 0x01; see deriveFileKey in the web client), so the ciphertext itself cannot be opened without the password — the server-side check is only a first gate. Ceiling: 100 MB for guests, 500 MB for accounts (e2ee_too_large). Refused with private_link_disabled where the server has it off.

encMetastring

Required with encryption: e2ee. base64 of nonceBase || AES-GCM(K, {n, t, s}) — the file name, MIME type and plaintext size under the file key — so the owner's dashboard can show a name without the key ever leaving the browser.

wrappedKeystring

Accounts only, required with encryption: e2ee: base64 of the file key wrapped for the account's wallet vault (AES-GCM under a key derived from a wallet signature). Guests must omit it (e2ee_vault_forbidden); an account that omits it is refused (e2ee_vault_required).

Example request

{
  "fileName": "document.pdf",
  "sizeBytes": 1048576,
  "payoutAddress": "0x1234567890abcdef1234567890abcdef12345678"
}

Response

Upload initialized

uploadIdstring required
shareHashstring required
uploadUrlstring uri required
uploadTokenstring required

Bearer token for the direct upload POST, valid 5 minutes from init and checked only when the upload starts — a slow transfer that began in time is never cut off. If more than 5 minutes pass before you start (or before a retry), the worker answers 401 expired_upload_token: call init again.

expiresAtstring date-time required

When the stored file expires, not the upload token.

Example response

{
  "uploadId": "up_a1b2c3d4e5f6g7h8",
  "shareHash": "abc123xyz789"
}

Changes

No recorded changes to this operation across all 1 revision of this API.