Vertueal Docs

Sharing API Endpoints

Create, retrieve, and consume encrypted ephemeral burn-on-read secret shares via the REST API.

Sharing API Endpoints

The Sharing API enables programmatic creation and consumption of encrypted ephemeral secrets (Protected Links). Secrets are encrypted client-side before submission—the server stores only opaque ciphertext blobs and never possesses decryption keys.

Note

Recipients do not need a Vertueal account to consume a shared secret. The decryption key is transmitted out-of-band via the URL anchor fragment (#key), which browsers never send to the server.


1. Create an Ephemeral Share

POST /api/share

Stores a client-side encrypted secret payload on the server and returns a unique shareId. The client is responsible for encrypting the plaintext secret using AES-256-GCM before calling this endpoint.

Rate Limit

WindowMaximum RequestsScope
60 seconds5Per IP address

Request Headers

Content-Type: application/json

Request Body Schema

FieldTypeRequiredDefaultDescription
data_blobstringYes—Base64-encoded AES-256-GCM encrypted secret payload.
meta_blobstringNonullOptional Base64-encoded encrypted metadata (e.g., label, sender name).
ivstringYes—Base64-encoded initialization vector used during AES-GCM encryption.
one_timebooleanNotrueIf true, the share is atomically deleted from the database upon first retrieval (burn-on-read).
expires_in_hoursnumberNo24Time-to-live in hours before the share expires. Maximum: 168 (7 days).

Code Examples

cURL
curl -X POST "https://passwordmanager.vertueal.com/api/share" \
  -H "Content-Type: application/json" \
  -d '{
    "data_blob": "U2FsdGVkX1+vupppZksvRf5pq5g5XjFRl...",
    "meta_blob": "U2FsdGVkX1+abc123metadata...",
    "iv": "YWJjZGVmMTIzNDU2Nzg5MA==",
    "one_time": true,
    "expires_in_hours": 24
  }'
TypeScript (fetch)
const response = await fetch("https://passwordmanager.vertueal.com/api/share", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    data_blob: encryptedPayload,   // AES-256-GCM ciphertext (Base64)
    meta_blob: encryptedMeta,      // Optional encrypted label
    iv: initializationVector,      // Base64-encoded IV
    one_time: true,
    expires_in_hours: 24,
  }),
});

const { shareId, expiresAt } = await response.json();

// Construct the full protected link with out-of-band decryption key
const protectedLink = `https://passwordmanager.vertueal.com/share/${shareId}#${ephemeralKeyHex}`;
Python (requests)
import requests

response = requests.post(
    "https://passwordmanager.vertueal.com/api/share",
    json={
        "data_blob": encrypted_payload,   # AES-256-GCM ciphertext (Base64)
        "meta_blob": encrypted_meta,      # Optional encrypted label
        "iv": initialization_vector,      # Base64-encoded IV
        "one_time": True,
        "expires_in_hours": 24,
    },
)

data = response.json()
share_id = data["shareId"]
protected_link = f"https://passwordmanager.vertueal.com/share/{share_id}#{ephemeral_key_hex}"

Success Response (200 OK)

{
  "success": true,
  "shareId": "550e8400-e29b-41d4-a716-446655440000",
  "expiresAt": "2026-09-21T18:30:00.000Z"
}

Error Responses

StatusBodyCause
400{ "error": "Invalid payload" }Missing required data_blob or iv fields.
429{ "error": "Too many requests" }Exceeded 5 share creations per 60-second window.
500{ "error": "Share creation failed" }Internal server error during database write.

2. Retrieve (and Consume) an Ephemeral Share

GET /api/share

Fetches the encrypted payload for a given share. If the share was created with one_time: true, the record is atomically deleted from the database immediately upon retrieval (burn-on-read).

Query Parameters

ParameterTypeRequiredDescription
idstringYesThe unique shareId returned during creation.

Code Examples

cURL
curl -X GET "https://passwordmanager.vertueal.com/api/share?id=550e8400-e29b-41d4-a716-446655440000"
TypeScript (fetch)
const shareId = "550e8400-e29b-41d4-a716-446655440000";
const response = await fetch(
  `https://passwordmanager.vertueal.com/api/share?id=${shareId}`
);

const { data_blob, meta_blob, iv, created_at } = await response.json();

// Extract the ephemeral key from the URL anchor fragment
const ephemeralKey = window.location.hash.substring(1);

// Decrypt data_blob using AES-256-GCM with ephemeralKey and iv
const plaintext = await decryptWithAESGCM(data_blob, ephemeralKey, iv);
Python (requests)
import requests

share_id = "550e8400-e29b-41d4-a716-446655440000"
response = requests.get(
    "https://passwordmanager.vertueal.com/api/share",
    params={"id": share_id},
)

data = response.json()
# Decrypt data["data_blob"] using AES-256-GCM with the ephemeral key and data["iv"]

Success Response (200 OK)

{
  "data_blob": "U2FsdGVkX1+vupppZksvRf5pq5g5XjFRl...",
  "meta_blob": "U2FsdGVkX1+abc123metadata...",
  "iv": "YWJjZGVmMTIzNDU2Nzg5MA==",
  "created_at": "2026-09-20T18:30:00.000Z"
}

Warning

If the share was created with one_time: true, this response is returned exactly once. Any subsequent request for the same shareId returns 404 Not Found. The secret is permanently and irrevocably deleted from the database.

Error Responses

StatusBodyCause
400{ "error": "Missing ID" }The id query parameter was not provided.
404{ "error": "Link not found or expired" }Share does not exist, has already been consumed (burn-on-read), or has expired via TTL.
500{ "error": "Retrieval failed" }Internal server error during database query.

End-to-End Sharing Flow

The complete lifecycle of a Protected Link from creation to consumption:

Loading diagram...

Tip

The ephemeral decryption key (K) is embedded in the URL anchor fragment (#...). Per RFC 3986, browsers never transmit anchor fragments in HTTP requests. The server therefore never possesses the key material required to decrypt the shared secret.

On this page