Kyndex
Guides

Entity Onboarding

Set up an organization in Literal, invite members, and start sharing encrypted documents through the public API.

Set up an organization in Literal, invite members, and start sharing encrypted documents — all through the public API.

This guide walks through the full entity onboarding workflow: creating an entity, adding members, claiming membership, uploading documents, and sharing within the organization. Every operation uses the Literal public API and follows the platform's zero-knowledge architecture — the server never sees your data in plaintext.

Prerequisites — Before starting, make sure you have:

  • A registered Literal account with an active session (see Getting Started)
  • A valid access token (Bearer or cookie-based authentication)
  • Admin key credentials (for entity creation only)

Overview

Literal distinguishes between two scopes of operation:

  • Consumer scope — a personal context where an individual manages documents and keys independently. No organization is involved.
  • Institutional scope — an entity-level context where users operate as members of an organization, sharing documents, search indexes, and encryption keys across the membership.

When you create an entity, you're establishing an institutional scope. A single user can operate in both scopes — managing personal documents while also collaborating within one or more entities.

For a deeper look at how entities work under the hood, see Entities & Memberships.

Step 1 — Create An Entity

Entity creation is an admin operation that requires admin key authentication. When you create an entity, the secure enclave generates a unique Entity Master Key (EMK) that becomes the cryptographic root of all entity-level encryption. The EMK is encrypted and stored on the server, but the plaintext EMK never leaves the enclave.

What Happens Behind The Scenes

  1. EMK Generation — The enclave generates a 32-byte Entity Master Key (EMK) using a cryptographically secure random source.
  2. Key Derivation — Using HKDF, the enclave derives entity-level keys from the EMK:
    • Entity Encryption Key (EEK) — derived per entity, used to encrypt the organization name and metadata; wrapped per-member so each member can decrypt entity metadata client-side
    • Blind Index Key (BIK) — derived per entity, used to create entity-scoped search tokens
  3. Admin Wrapping — The enclave wraps the EEK with the admin user's hybrid public key (ML-KEM + X25519), so only the admin can unwrap it to decrypt entity metadata.
  4. Entity Metadata Encryption — The organization name and metadata are encrypted with a derived key and stored as name_encrypted and metadata_encrypted.
  5. Database Storage — The server stores only encrypted values: entity_secret_encrypted (the EMK wrapped for KMS), entity metadata, and a cryptographic token for entity membership verification.

No plaintext EMK, metadata, or member keys are ever transmitted to the server.

Request

POST /admin/entities
Authorization: Admin <admin-key>
Content-Type: application/json
{
  "admin_user_id": "b7f5a6e7-c8d9-4405-f1a2-b3c4d5e6f7a8",
  "entity_type": "organization",
  "encrypted_payload": "<base64-encoded AES-256-GCM ciphertext>"
}
FieldTypeDescription
admin_user_idUUIDThe user ID who will become the entity's first admin
entity_typestring"organization" (default); scope for the entity
encrypted_payloadstringBase64-encoded ciphertext containing the entity name and metadata. Encrypt this client-side before transmission using a derived key.

About encrypted_payload:

The payload is the entity name, metadata, and other organizational details encrypted with a client-derived key before being sent to the server. The exact encryption scheme and key derivation depend on your client implementation, but must produce a ciphertext that the enclave can decrypt using the corresponding decryption key.

Zero-Knowledge Note — The entity name and metadata are encrypted on your device and remain opaque to the server. The server stores only the ciphertext (name_encrypted, metadata_encrypted). The secure enclave decrypts this data during processing but never returns plaintext to the server. Only the admin and authorized members can decrypt the organization's metadata using keys derived from the EMK.

Response

201 Created
Location: /v1/entities/<entity-id>
{
  "id": "e4c2d3b4-f5a6-4172-c8d9-e0f1a2b3c4d5",
  "entity_type": "organization",
  "created_at": "2026-03-09T15:00:00.000Z"
}

What The Admin Receives

After successful creation:

  1. The admin is automatically assigned the admin role in the entity.
  2. A membership record is created for the admin (no claim step needed for the creator).
  3. The admin can immediately:
    • Add new members to the entity
    • Upload and share documents within the organization
    • Search the entity's document pool using entity-scoped search tokens

No further action is required for the admin to start using the entity. The encrypted EMK remains on the server; the admin's wrapped EEK is stored in their membership record, encrypted with the admin's hybrid public key.

Step 2 — Add Members

Once the entity exists, an admin can add other users as members. This requires an active session with admin privileges in the entity.

Request

POST /v1/entities/{id}/memberships
Authorization: Bearer <access-token>
Content-Type: application/json
{
  "user_id": "b7f5a6e7-c8d9-4405-f1a2-b3c4d5e6f7a8",
  "role": "member"
}
FieldTypeDescription
user_idUUIDThe user to add to the entity
rolestring"admin" or "member" (defaults to "member")

Authorization: Only entity admins can add members.

Behind the scenes, two cryptographic hash-lock commitments are created — one from the member's encryption key and one from their signing key. Both must be satisfied during the claim step. This ensures that only the intended person can complete the membership claim — even if the invitation is intercepted.

Response

201 Created
Location: /v1/entities/<entity-id>/memberships/<membership-id>
{
  "id": "a6e4f5d6-b7c8-4394-e0f1-a2b3c4d5e6f7",
  "role": "member",
  "euk_epoch": 0,
  "is_active": true,
  "created_at": "2026-03-09T15:05:00.000Z",
  "updated_at": "2026-03-09T15:05:00.000Z"
}

The membership is created in a pending state until the member claims it. The is_active field reflects the current membership status.

Step 3 — Claim Membership

The new member must claim their membership to complete the onboarding. This involves a cryptographic proof-of-possession that verifies the member holds the private key matching the hash-lock commitment.

Request

PUT /v1/entities/{id}/memberships/{mid}/claim
Authorization: Bearer <access-token>
Content-Type: application/json
{
  "user_member_token": "<base64-encoded 32-byte HMAC token>",
  "mldsa_vk": "<base64-encoded hybrid verifying key>",
  "signature": "<base64-encoded hybrid signature>",
  "delivery_mlkem_ek": "<base64-encoded ML-KEM encapsulation key>",
  "delivery_dsa_vk": "<base64-encoded DSA verifying key>"
}
FieldTypeDescription
user_member_tokenstringA one-way HMAC token that identifies this user's memberships without revealing user identity
mldsa_vkstringThe member's hybrid ML-DSA-65 + Ed25519 verifying key (base64)
signaturestringHybrid signature proving possession of the signing key (base64)
delivery_mlkem_ekstringPer-entity ML-KEM encapsulation key for receiving encrypted document deliveries (base64)
delivery_dsa_vkstringPer-entity DSA verifying key for delivery authentication (base64)

The server verifies:

  1. The hash of the verifying key matches the commitment stored at add-member time
  2. The signature is valid over a canonical claim message

Response

{
  "claimed": true
}

After claiming, the member can decrypt entity metadata using their wrapped entity encryption key. Access to specific entity documents requires the document owner to share them through grants or entity deliveries — claiming alone does not grant document access.

Step 4 — List Your Entities

Any authenticated user can list the entities they belong to.

GET /v1/entities
Authorization: Bearer <access-token>

Response

{
  "memberships": [
    {
      "membership_id": "a6e4f5d6-b7c8-4394-e0f1-a2b3c4d5e6f7",
      "entity_id": "e4c2d3b4-f5a6-4172-c8d9-e0f1a2b3c4d5",
      "role": "member",
      "euk_epoch": 0,
      "name_encrypted": "<base64 ciphertext>",
      "metadata_encrypted": "<base64 ciphertext>"
    }
  ]
}

Entity names and metadata are returned as encrypted blobs. Your client decrypts them locally using the entity key derived from your session.

Step 5 — Upload A Document

Document upload works the same way in both consumer and institutional scopes. The key difference is how search tokens and keys are scoped after upload.

  1. Encrypt the document locally — generate a fresh document encryption key (DEK), encrypt the content and metadata, and wrap the DEK with your user master key.
  2. Reserve a slotPOST /v1/documents/reservations to obtain a document ID and commitment nonce, then POST /v1/documents with the encrypted metadata and wrapped keys.
  3. Upload the encrypted contentPUT /v1/documents/{id}/content with the binary ciphertext.
  4. Wait for processing — poll GET /v1/documents/{id} until status reaches processed.

For a detailed walkthrough of the document lifecycle, see Document Lifecycle.

Step 6 — Share A Document Within Your Entity

To share a document with entity members, you use Literal's grant system. Grants are time-limited, revocable, and fully zero-knowledge.

The high-level flow:

  1. Create a grantPOST /v1/grants with the recipient's public key, a sealed payload containing the wrapped DEK, and an expiration time.
  2. Recipient discovers the grant — the recipient periodically checks for grants using view tags (GET /v1/grants?view_tags=...).
  3. Recipient claims the grant — the recipient proves their identity and claims the grant.
  4. You approve the claim — review and accept the claim to activate access.
  5. Re-index for entity searchPOST /v1/documents/{id}/index-jobs triggers the secure enclave to generate entity-scoped search tokens, so the document becomes searchable within the organization. See Job Polling for the full challenge/submit flow used to track index job completion.

For the full grant lifecycle and API details, see Grants & Sharing.

Entity-Level Encryption — Each entity has its own derived encryption keys. When a document is shared with an entity, the secure enclave generates entity-scoped search tokens using the organization's key. These tokens are independent of your personal tokens, so the server cannot correlate personal and organizational searches. For details on how these keys are structured, see Key Hierarchy.

Managing Members

Admins can list and remove members at any time.

List Members

GET /v1/entities/{id}/memberships
Authorization: Bearer <access-token>

Returns all active members with their roles, membership IDs, and timestamps. Requires admin role.

Remove A Member

DELETE /v1/entities/{id}/memberships/{membershipId}
Authorization: Bearer <access-token>

Returns 204 No Content on success. Requires admin role. The membership is soft-deleted and the member's access to entity resources is revoked.

Roles And Permissions

RoleCan Add MembersCan Remove MembersCan Access Entity DocumentsCan Search Entity Document Pool
Admin
Member

Error Handling

All entity endpoints return errors in RFC 9457 Problem Details format:

{
  "type": "https://api.kyndex.co/errors/FORBIDDEN",
  "title": "Forbidden",
  "status": 403,
  "detail": "Only entity admins can add members"
}
StatusMeaningCommon Cause
400Bad RequestInvalid request body or parameters
401UnauthorizedExpired or missing access token
403ForbiddenInsufficient role (e.g., member trying to add members)
404Not FoundEntity or user does not exist
409ConflictUser is already a member of the entity
429Rate LimitedToo many requests — back off and retry

On this page