Capsule API
HTTP API endpoints available to your application at 127.0.0.1:18000 inside the enclave.
The Capsule API consists of two services: the Primary API (full /v1/* surface) and the Aux API (restricted attestation proxy). Both bind to 127.0.0.1 only, with a 10 MiB request body limit.
Endpoint Overview
storage.s3.enabled: true)kms_integration.enabled: true)kms_integration.use_app_wallet: true)Ethereum APIs
GET /v1/eth/address
Returns the enclave's Ethereum address and secp256k1 public key. The key is deterministic per enclave instance lifetime.
GET http://127.0.0.1:18000/v1/eth/address
{
"address": "0x1234...abcd",
"public_key": "0x04..."
}
POST /v1/eth/sign
Signs a UTF-8 string using the Ethereum personal-sign prefix.
POST http://127.0.0.1:18000/v1/eth/sign
Content-Type: application/json
{
"message": "Hello, World!"
}
{
"signature": "0x..."
}
POST /v1/eth/sign-tx
Signs an EIP-1559 transaction. Accepts structured fields or raw RLP.
POST http://127.0.0.1:18000/v1/eth/sign-tx
Content-Type: application/json
{
"chain_id": 84532,
"nonce": 0,
"to": "0xRecipientAddress",
"value": "0x0",
"data": "0x",
"max_fee_per_gas": "0x59682F00",
"max_priority_fee_per_gas": "0x3B9ACA00",
"gas_limit": 21000
}
Encryption APIs
End-to-end encryption between client and enclave using P-384 ECDH + HKDF-SHA256 + AES-256-GCM.
Cryptographic Protocol
Key agreement: P-384 ECDH | KDF: HKDF-SHA256 | Cipher: AES-256-GCM | Nonce: 12 bytes
HKDF info string: "capsule-ecdh-aes256gcm-v1"
Salt derivation: sort lexicographically(client_pub_sec1, enclave_pub_sec1) || nonce
GET /v1/encryption/public_key
{
"public_key_der": "0x3076...",
"public_key_pem": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----"
}
POST /v1/encryption/decrypt
{
"nonce": "0x...",
"client_public_key": "0x...",
"encrypted_data": "0x..."
}
{
"plaintext": "decrypted string"
}
0x prefix. client_public_key is DER/SPKI format. Plaintext must be valid UTF-8. Duplicate (client_public_key, nonce) pairs are rejected.
POST /v1/encryption/encrypt
{
"plaintext": "string to encrypt",
"client_public_key": "0x..."
}
{
"encrypted_data": "a1b2c3...",
"enclave_public_key": "3076...",
"nonce": "d4e5f6..."
}
0x prefix.
Client Integration Flow
Get enclave public key
GET /v1/encryption/public_key or extract from attestation document.
Generate client P-384 keypair
Create an ephemeral P-384 key pair on the client side.
Derive shared secret
ECDH(client_private, enclave_public) → HKDF-SHA256 with sorted public keys and nonce as salt.
Encrypt and send
Generate a fresh 12-byte nonce per message. Encrypt with AES-256-GCM. Send ciphertext, nonce, and client DER public key to /v1/encryption/decrypt.
S3 Storage APIs
Requires storage.s3.enabled: true in capsule.yaml. Egress access to IMDS (169.254.169.254) and S3 endpoints is required.
POST /v1/s3/put
{
"key": "data/record.json",
"body": "{\"id\": 1, \"name\": \"test\"}"
}
POST /v1/s3/get
{
"key": "data/record.json"
}
POST /v1/s3/delete
{
"key": "data/record.json"
}
POST /v1/s3/list
{
"prefix": "data/",
"max_keys": 100,
"continuation_token": null
}
Key Path Security
All keys are prefixed with the configured storage.s3.prefix. Keys containing .. or absolute paths are rejected. When encryption.mode: kms is used, objects are automatically encrypted with KMS-derived keys.
Auxiliary API
A restricted proxy on port 18001 (default, or api_port + 1). Required for external attestation flows.
Purpose
The Aux API provides a safe attestation endpoint for external clients. It forwards POST /v1/attestation to the Primary API but sanitizes the response by removing the public_key field.
When to Expose
Add the Aux API port to your ingress list when external clients need to fetch attestation documents. Never expose the Primary API port externally.
Configuration
Set aux_api.listen_port in capsule.yaml. Defaults to the primary API port + 1 if omitted.
Mock Service for Development
Develop locally without running a real enclave.
External Mock Endpoint
Available at http://capsule-runtime.sparsity.cloud:18000/ — hosted by the Nova Platform team. Not version-locked to your Capsule Runtime. Use for lightweight development only.
# In your application:
# Set CAPSULE_API_MOCK_URL environment variable to point to the mock
# When IN_ENCLAVE is not set, use CAPSULE_API_MOCK_URL
# When IN_ENCLAVE=true, use http://127.0.0.1:18000
# Quick test:
curl http://capsule-runtime.sparsity.cloud:18000/v1/eth/address
curl http://capsule-runtime.sparsity.cloud:18000/v1/random
Mock Limitations
Not all endpoints may be available. Response formats may differ from the real API. Error codes and edge-case behavior may not match. Always verify against a real enclave before production.