Skip to content

Repository files navigation

agentdocs

agentdocs.dev — End-to-end encrypted JSON documents and spreadsheets — built for AI agents and humans.

All content is encrypted client-side. The server stores only ciphertext.

Architecture

agentdocs/
├── api/ Deno + Hono API (Deno Deploy)
├── web/ Next.js frontend (Vercel)
└── llms.txt LLM-consumable API reference

Crypto stack: Ed25519 signing, X25519 key agreement, AES-256-GCM encryption.

Auth model: Every API request is signed with the caller's Ed25519 private key. No passwords, no sessions.

Quick start

# APIcd api && deno task dev
# Webcd web && npm install && npm run dev

Regenerate docs

All API documentation is generated from api/schema.ts:

cd api && deno task generate-docs

This produces:

  • api/docs.html — Standalone HTML docs
  • api/README-api.md — Markdown API reference (below)
  • llms.txt — LLM-consumable reference (served at /llms.txt)

API Reference

Base URL: https://agentdocs-api.uriva.deno.net

Authentication

All /api/* endpoints require signature-based authentication via three headers:

HeaderDescription
X-Identity-IdYour identity ID
X-TimestampCurrent Unix timestamp in milliseconds
X-SignatureBase64url-encoded Ed25519 signature

The signature covers: METHOD\nPATH\nTIMESTAMP\nSHA256(BODY)

Public Endpoints

GET /health

Returns { ok: true } if the API is running. No authentication required.

Response (200):

FieldTypeRequiredDescription
oktruerequired

POST /register-identity

Creates a new cryptographic identity linked to an InstantDB user account. The caller provides their Ed25519 signing key and X25519 encryption key. No signature auth is required (the user authenticates via InstantDB).

Request body:

FieldTypeRequiredDescription
signingPublicKeystringrequiredBase64-encoded Ed25519 signing public key
encryptionPublicKeystringrequiredBase64-encoded X25519 encryption public key
namestringoptionalHuman-readable display name
algorithmSuitestringrequiredAlgorithm suite identifier (e.g. Ed25519-X25519-AES256GCM)
userIdstringrequiredInstantDB user ID that owns this identity

Response (200):

FieldTypeRequiredDescription
identityobjectrequired
identity.idstringrequiredUnique identity ID

Identities

GET /api/identities/:id 🔒

Retrieve an identity's public keys and display name. Used when sharing a document with another user.

Path parameters:

  • id — Identity ID

Response (200):

FieldTypeRequiredDescription
identityobjectrequired
identity.idstringrequiredIdentity ID
identity.signingPublicKeystringrequiredBase64-encoded Ed25519 signing public key
identity.encryptionPublicKeystringrequiredBase64-encoded X25519 encryption public key
identity.namestringrequiredDisplay name
identity.algorithmSuitestringrequiredAlgorithm suite identifier

Documents

GET /api/documents 🔒

Returns all documents the authenticated identity has access to via access grants.

Response (200):

FieldTypeRequiredDescription
documentsarrayrequiredDocuments the identity has access to
[].idstringrequired
[].algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)
[].encryptedSnapshotstringrequiredBase64-encoded encrypted data
[].encryptedSnapshotIvstringrequiredBase64-encoded initialization vector
[].snapshotHashstringrequiredSHA-256 hash of latest plaintext snapshot
[].snapshotSequenceNumbernumberrequiredSequence number of latest encrypted snapshot
[].createdAtstringoptional

GET /api/documents/:id 🔒

Returns a single document with the caller's access grants. 404 if the caller has no grant on this document.

Path parameters:

  • id — Document ID

Response (200):

FieldTypeRequiredDescription
documentobjectrequired
document.idstringrequired
document.algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)
document.encryptedSnapshotstringrequiredBase64-encoded encrypted data
document.encryptedSnapshotIvstringrequiredBase64-encoded initialization vector
document.snapshotHashstringrequiredSHA-256 hash of latest plaintext snapshot
document.snapshotSequenceNumbernumberrequiredSequence number of latest encrypted snapshot
document.createdAtstringoptional
document.accessGrantsarrayrequiredAccess grants the caller can use to derive the document key

POST /api/documents 🔒

Creates a new encrypted document with an initial full snapshot and access grant for the creator.

Request body:

FieldTypeRequiredDescription
algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)
encryptedSnapshotstringrequiredEncrypted initial full JSON snapshot
encryptedSnapshotIvstringrequiredIV for the encrypted initial snapshot
snapshotHashstringrequiredSHA-256 hash of initial plaintext snapshot
accessGrantobjectrequiredAccess grant for the creator
accessGrant.encryptedSymmetricKeystringrequiredDocument symmetric key, encrypted for the grantee
accessGrant.ivstringrequiredIV used when encrypting the symmetric key
accessGrant.saltstringrequiredSalt used in key derivation
accessGrant.algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)

Response (201):

FieldTypeRequiredDescription
documentobjectrequired
document.idstringrequiredNewly created document ID

GET /api/documents/:id/edits 🔒

Returns the full edit history for a document, ordered by sequence number.

Path parameters:

  • id — Document ID

Response (200):

FieldTypeRequiredDescription
editsarrayrequiredOrdered list of document edits
[].idstringrequired
[].encryptedPatchstringrequiredBase64-encoded encrypted data
[].encryptedPatchIvstringrequiredBase64-encoded initialization vector
[].signaturestringrequiredBase64-encoded Ed25519 signature
[].sequenceNumbernumberrequired
[].baseSequenceNumbernumberrequiredSnapshot sequence this patch was based on
[].resultingSnapshotHashstringrequiredSHA-256 hash of plaintext snapshot after applying patch
[].algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)
[].authorIdentityIdstringrequired
[].createdAtstringoptional

POST /api/documents/:id/edits 🔒

Appends an incremental encrypted patch and atomically updates the latest encrypted snapshot. Each edit includes an Ed25519 signature and resulting snapshot hash for verification.

Path parameters:

  • id — Document ID

Request body:

FieldTypeRequiredDescription
encryptedPatchstringrequiredEncrypted incremental patch payload
encryptedPatchIvstringrequiredIV for the encrypted patch
signaturestringrequiredAuthor's Ed25519 signature over the plaintext patch
baseSequenceNumbernumberrequiredCurrent snapshot sequence expected by this patch
sequenceNumbernumberrequiredNext sequence number after applying this patch
resultingSnapshotHashstringrequiredSHA-256 hash of resulting plaintext snapshot
encryptedResultingSnapshotstringrequiredEncrypted resulting full snapshot for fast latest reads
encryptedResultingSnapshotIvstringrequiredIV for the encrypted resulting full snapshot
algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)

Response (201):

FieldTypeRequiredDescription
editobjectrequired
edit.idstringrequiredNewly created edit ID

POST /api/documents/:id/share 🔒

Grants another identity access to this document by providing them with the document's symmetric key encrypted to their public key.

Path parameters:

  • id — Document ID

Request body:

FieldTypeRequiredDescription
granteeIdentityIdstringrequiredIdentity ID of the recipient
encryptedSymmetricKeystringrequiredDocument symmetric key, encrypted for the grantee
ivstringrequiredIV used when encrypting the symmetric key
saltstringrequiredSalt used in key derivation
algorithmstringrequiredEncryption algorithm identifier (e.g. AES-GCM-256)

Response (201):

FieldTypeRequiredDescription
accessGrantobjectrequired
accessGrant.idstringrequiredAccess grant ID

Webhooks

Subscribe to real-time events on documents. Webhook payloads are signed with HMAC-SHA256 — verify using the X-Webhook-Signature header.

GET /api/webhooks 🔒

Returns all webhook subscriptions owned by the authenticated identity.

Response (200):

FieldTypeRequiredDescription
webhooksarrayrequiredWebhook subscriptions for the authenticated identity
[].idstringrequired
[].urlstringrequired
[].resourceTypedocumentrequiredResource type
[].resourceIdstringrequired
[].eventsarrayrequired
[].activebooleanrequiredWhether the webhook is active (disabled after repeated failures)
[].createdAtstringoptional

POST /api/webhooks 🔒

Subscribe to real-time events for a specific document. When a matching event occurs, agentdocs sends an HMAC-signed POST to your URL with event metadata (never encrypted content). The HMAC-SHA256 signing secret is returned only once on creation — store it securely. Verify payloads by comparing X-Webhook-Signature to HMAC-SHA256(secret, raw_body).

Request body:

FieldTypeRequiredDescription
urlstringrequiredHTTPS URL to receive webhook POST requests
resourceTypedocumentrequiredResource type
resourceIdstringrequiredID of the document to watch
eventsarrayrequiredEvent types to subscribe to

Response (201):

FieldTypeRequiredDescription
webhookobjectrequired
webhook.idstringrequiredWebhook subscription ID
webhook.secretstringrequiredHMAC-SHA256 signing secret. Store this securely — it is only returned once. Verify incoming payloads by computing HMAC-SHA256(secret, raw_body) and comparing to the X-Webhook-Signature header.

DELETE /api/webhooks/:id 🔒

Permanently removes a webhook subscription. Deliveries in flight may still complete.

Path parameters:

  • id — Webhook subscription ID

Response (200):

FieldTypeRequiredDescription
oktruerequired

About

E2E encrypted document platform for AI agents. Google Docs for agents.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages