Skip to content

Create an encrypted area

Encrypts a piece of text or an uploaded file end-to-end and returns the new area's id. Use it to share a credential, an API key, a private note, or a sensitive file: choose who it is for, set the optional controls, and Aitronos either delivers it for you or hands you a secure link to forward yourself.

Aitronos never holds a key that can read the area. For a secure link, the decryption key travels in the link's URL fragment (the part after #), which browsers never send to a server — so the key never reaches Aitronos. Storage holds ciphertext only.

POSThttps://api.aitronos.com/v1/encrypted-areas

Requires authentication (bearer token or API key). The authenticated caller is the sender, so there is no separate approval step. Creates are limited to 30 per minute per user; beyond that the endpoint answers 429 with a retry_after in seconds.

Encrypted areas are part of Conversations. Where Conversations is enabled for your account, encrypted areas are enabled with it and this endpoint works; where Conversations is switched off, the endpoint answers 403. There is nothing extra to turn on.

Three rules to read before you call this

  • The secure link is returned exactly once and can never be re-issued. The key inside it is never stored, so nobody — including Aitronos — can produce the link again. If your client loses the response body, the area is unrecoverable and you must create a new one. Capture secure_link the moment you receive it.
  • secure_link is returned only when audience is link. Every other audience is delivered for you, so the response deliberately withholds the key-bearing URL.
  • This endpoint is not idempotent. Repeating the same request creates a second, independent area with its own key — there is no de-duplication. Retry only when you know the first call did not return a 201.

Controls and their defaults

ControlDefaultNotes
audience(no default — required)Selects the security model.
passwordnoneOptional. Share it with the recipient yourself, over a different channel.
burn_after_readoffOptional. The area self-destructs after the first successful open.
expiry1wThe area expires after 7 days unless you choose otherwise. Pick never explicitly if it should never expire.

burn_after_read and expiry apply to every audience — they are enforced by the server on both the secure-link and the identity-sealed path.

password applies only to the secure-link audiences. It feeds the key derivation, and an identity-sealed area has nowhere to carry it, so a password sent with an area that gets sealed to another Aitronos user's identity is dropped: the response reports password_required: false and names it in controls_not_applied. Read that list rather than inferring the drop from crypto_mode.

Body parameters

audience string required

Who the area is for. One of user, email, whatsapp, imessage, slack, teams, link. user seals the area to another Aitronos user's identity in your organization — the strongest option, because a forwarded copy stays sealed to them. email and the four messaging values send a secure link over that channel. link creates a shareable secure link with no named recipient and returns it to you.

Exactly one recipient field must be supplied, and it must be the one that matches the audience. Supplying a field the audience does not accept, more than one, or none at all is a 422.

audienceSupply exactly one of
userrecipient_user_id
emailrecipient_email or recipient_contact_id
whatsapprecipient_handle, recipient_contact_id, or the legacy recipient_whatsapp
imessage, slack, teamsrecipient_handle or recipient_contact_id
link(none — a recipient field is rejected)

recipient_user_id string optional

Required when audience is user: the Aitronos user id of the recipient, who must be in the same organization. Must be omitted for every other audience. Max 255 characters.

recipient_email string optional

Required when audience is email, unless you supply recipient_contact_id instead: the recipient's email address. Must be omitted for every other audience. Max 320 characters.

recipient_handle string optional

Required for the messaging audiences, unless you supply recipient_contact_id instead: the recipient's address on that channel — a phone number in E.164 form (for example +41791234567) for whatsapp and imessage, a member id for slack, a directory object id for teams. Must be omitted for the user, email and link audiences. Max 320 characters.

recipient_contact_id string optional

An existing contact to send to, instead of a raw address. Accepted for the four messaging audiences, and for email when the send should go over that contact's email channel. Provide either this or the audience's address field, never both. Must be omitted for user and link. Max 255 characters.

recipient_whatsapp string optional

Legacy alias of recipient_handle, accepted only when audience is whatsapp. Provide exactly one of the two, never both. Prefer recipient_handle for new integrations. Max 320 characters.

content_text string optional

The secret to encrypt, as inline text. Provide content_text, file_ref, or both — supplying neither is a 422. Sent together, the note is sealed alongside the file and the recipient reads it without opening the attachment. Preserved byte for byte, including leading and trailing whitespace, because whitespace can be meaningful in a secret. Never stored in readable form and never written to a log. Max 1,048,576 characters — use file_ref for anything larger.

file_ref string optional

The id of an already-uploaded file to encrypt, which must belong to you. Provide content_text, file_ref, or both. Use this rather than content_text for anything larger than a short secret. Max 255 characters.

Any file type is accepted, including an archive of several files — upload it through the encrypted-area upload endpoint first. That endpoint takes arbitrary bytes, because a file sealed here is encrypted rather than read; the general file upload restricts types because it parses and indexes what you send it.

Two size limits apply, and the lower one depends on the audience. A file sealed to another Aitronos user's identity may be up to the full encrypted-area limit (100 MB). A file sent as a secure link — every audience except an enrolled user recipient — may be up to 32 MB, because that format carries the file inside the sealed payload. A file between the two is refused with 413 and reason: attachment_too_large_external rather than sealed into a link nobody could open.

title string optional

A display label shown to the recipient alongside the sealed card. Not secret — it is rendered into the card and, for the user audience, stored as part of the delivered message. Never put any part of the secret here. Defaults to Encrypted area. Max 120 characters.

password string optional

A password the recipient must enter to open the area. It is folded into the key derivation on the recipient's device, is never sent to Aitronos when they open the area, and is never echoed back, delivered, or logged — share it with the recipient yourself, over a different channel. Off by default. Preserved byte for byte. Max 1024 characters.

burn_after_read boolean optional

When true, the area self-destructs after the first successful open. Defaults to false. Must be a real boolean — a string such as "true" is rejected with a 422, because silently enabling a destructive option would be worse than an error.

expiry string optional

How long the area stays openable. One of 1h, 1d, 1w, 30d, never. Defaults to 1w — the area expires after 7 days unless you choose otherwise. Choose never explicitly if it should not expire.

Unknown fields are rejected with a 422 rather than ignored, so a misspelled control can never be silently dropped.

Returns

201 Created. The response is marked Cache-Control: no-store.

Retry on 503, never on 500. The two storage failures are reported differently on purpose, and only one is worth retrying. A 503 is transient: it carries a Retry-After header (and a retry_after field, in seconds), and the same request will likely succeed shortly. A 500 is a configuration fault on our side that a retry can never clear — surface it and stop rather than looping. In both cases nothing was created: an area exists only once you have received a 201 with an encbin_id.

encbin_id string · The new area's id (encbin_-prefixed). Use it with the fetch endpoints. audience string · The audience the area was actually sealed for. crypto_mode string · recipient_bound when sealed to a recipient's identity, or external when opened by a key carried in the link. format_version string · The sealing format the area was written in. fell_back_to_link boolean · true when a user audience could not be sealed to that user's identity (they have no key enrolled) and was sealed as a recipient-addressed secure link instead. secure_link string · The complete secure link, including the decryption key in its URL fragment. Present only for audience: "link", returned only once, and never re-issuable. null for every other audience. Treat it as the secret it is. sealed_card_token string · The chat token that renders the sealed card for this area. It carries the area id, audience and title only — never a key and never the content. recipient_ref string · A non-secret echo of who the area was addressed to (a user id, an email address, or a channel handle). null for audience: "link". password_required boolean · Whether a password is needed to open the area, as resolved — an identity-sealed area ignores a requested password and reports false. burn_after_read boolean · Whether the area self-destructs on first open, as resolved. expires_at string · When the area stops being openable (ISO-8601, UTC), as resolved, or null when it does not expire. This endpoint emits the numeric-offset form (2026-08-01T09:00:00.103591+00:00); the fetch endpoints emit the same instant in the Z form. Parse it with a real ISO-8601 parser rather than matching on a Z suffix. controls_not_applied array of strings · The controls you asked for that this area does not carry. Empty when nothing was dropped. Today the only member is "password", and it appears only when a password was sent and the area was sealed to a recipient's identity. It is keyed off what you requested, so an identity-sealed area created without a password returns [] rather than advertising a loss you never asked for. Show this to the sender instead of comparing password_required against your request — a control this list does not name was applied. delivery object · How the area is being delivered. Six fields, below. security_disclosure object · Machine-readable security facts to show the sender. Seven fields, below.

delivery

status string · What this request did about delivery: returned_in_response (the link audience — the link is in this response and there is no send), queued (the delivery was recorded and fires once the area is durably stored), or not_queued (the delivery could not be recorded — the area exists but nothing will be sent). It describes the request, not the eventual send outcome. delivered boolean · Always false. Delivery happens after this response is returned, so no send outcome can honestly be reported here. detail string · A short human-readable note about the delivery. Never a secret. audience string · The audience the area was sealed for. channel string · The transport the area is delivered over — internal, email, whatsapp, imessage, slack, or teams — or null for audience: "link", which has no send. channel_delivery_available boolean · Whether this build can deliver to the chosen channel. It is currently true for every supported channel; a false would mean the area was created and sealed but will not be delivered. This describes the channel's support in this build, not your environment's configuration — it will not go false because a mail server is down or a messaging account is disconnected. Those surface as a failed delivery afterwards, not here. The field exists so a channel that is not yet supported can be identified without a change to this response shape.

security_disclosure

Facts only — your interface owns the wording.

level string · identity_sealed when the area is sealed to a specific recipient's identity (only they can open it, even if it is forwarded), or link_key when it is opened by a key carried in the link. key_travels_in_link boolean · Whether the decryption key rides in the link's URL fragment. The fragment never reaches Aitronos — but anywhere the link is pasted, the key goes with it. anyone_with_link_can_open boolean · Whether possession of the link alone is enough to open the area (true for a key-in-link area with no password). password_required boolean · Whether a password must be entered to open the area. burn_after_read boolean · Whether the area self-destructs after the first open. expires_at string · When the area stops being openable (ISO-8601, UTC), or null. Same numeric-offset form as the top-level expires_at above. fell_back_to_link boolean · true when a user audience was sealed as a secure link because the recipient has no key enrolled — worth surfacing, because the security level is then link_key rather than identity_sealed.

cURL
curl -X POST "https://api.aitronos.com/v1/encrypted-areas" \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "audience": "link",
    "content_text": "staging-db-password: hunter2",
    "title": "Staging database password",
    "burn_after_read": true,
    "expiry": "1d"
  }'

Response:

201 Created
{
  "encbin_id": "encbin_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",
  "audience": "link",
  "crypto_mode": "external",
  "format_version": "v2",
  "fell_back_to_link": false,
  "secure_link": "https://chat.aitronos.com/encrypted-area/encbin_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6#3xK9uQr7...",
  "sealed_card_token": "{{encrypted_area | id::encbin_a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6 | audience::link | title::Staging database password}}",
  "recipient_ref": null,
  "password_required": false,
  "burn_after_read": true,
  "expires_at": "2026-08-01T09:00:00.103591+00:00",
  "delivery": {
    "status": "returned_in_response",
    "delivered": false,
    "detail": "The secure link is in this response; forward it yourself.",
    "audience": "link",
    "channel": null,
    "channel_delivery_available": true
  },
  "security_disclosure": {
    "level": "link_key",
    "key_travels_in_link": true,
    "anyone_with_link_can_open": true,
    "password_required": false,
    "burn_after_read": true,
    "expires_at": "2026-08-01T09:00:00.103591+00:00",
    "fell_back_to_link": false
  }
}

For a delivered audience the shape is the same, with secure_link null, recipient_ref set, and delivery.status queued with the matching channel.