cloak.business

API Reference

Last Updated: 2026-03-06 API Version: 6.13.0


Overview#

The cloak.business API provides programmatic access to PII detection and anonymization services. All endpoints use HTTPS and return JSON responses.

Base URL: https://cloak.business/api


Table of Contents#

  1. Authentication
  2. Rate Limits
  3. Error Handling
  4. Text Endpoints
  5. Image Endpoints
  6. Asymmetric Key Endpoints
  7. Account Endpoints
  8. Utility Endpoints
  9. Request & Response Examples
  10. SDKs & Libraries

Authentication#

All API requests require authentication via a Bearer token in the Authorization header.

Getting Your API Key#

  1. Sign in at cloak.business
  2. Go to Dashboard > API Keys
  3. Click Create API Key
  4. Copy the key (it won't be shown again)

Using Your API Key#

curl -X POST https://cloak.business/api/presidio/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Contact John Doe at john@example.com"}'

Token Format#

API keys are 64-character alphanumeric strings prefixed with cb_:

cb_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2

Rate Limits#

Rate limits vary by endpoint and plan:

EndpointFreeBasicProfessionalEnterprise
/analyze10/min60/min120/min300/min
/anonymize10/min60/min120/min300/min
/batchN/A20/min60/min120/min
/imageN/A30/min60/min120/min
/deanonymize5/min30/min60/min120/min

When rate limited, you'll receive a 429 Too Many Requests response:

{
  "error": "Rate limit exceeded",
  "message": "Please wait before making another request",
  "retryAfter": 60
}

Error Handling#

HTTP Status Codes#

CodeMeaningDescription
200OKRequest succeeded
400Bad RequestInvalid parameters
401UnauthorizedInvalid or missing API key
402Payment RequiredInsufficient tokens
403ForbiddenFeature not available on plan
413Payload Too LargeText exceeds size limit
429Too Many RequestsRate limit exceeded
500Server ErrorInternal server error

Error Response Format#

{
  "error": "Error type",
  "message": "Human-readable description",
  "code": "MACHINE_READABLE_CODE",
  "details": {}
}

Common Error Codes#

CodeDescription
INSUFFICIENT_TOKENSNot enough tokens for operation
DAILY_LIMIT_EXCEEDEDDaily upload limit reached
MONTHLY_LIMIT_EXCEEDEDMonthly upload limit reached
INVALID_LANGUAGELanguage code not supported
TEXT_TOO_LONGText exceeds plan limit
FEATURE_NOT_AVAILABLEFeature requires plan upgrade

Text Endpoints#

Analyze Text#

Detect PII entities in text without modifying it.

Endpoint: POST /api/presidio/analyze

Request Body:

FieldTypeRequiredDescription
textstringYesText to analyze (max 100KB-1MB based on plan)
languagestringNoISO 639-1 code (default: en)
entitiesstring[]NoEntity types to detect (default: all)
score_thresholdnumberNoMinimum confidence (0.0-1.0, default: 0.35)
ad_hoc_recognizersobject[]NoCustom pattern recognizers

Example Request:

curl -X POST https://cloak.business/api/presidio/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Contact John Doe at john@example.com or call 555-123-4567",
    "language": "en",
    "entities": ["PERSON", "EMAIL_ADDRESS", "PHONE_NUMBER"],
    "score_threshold": 0.5
  }'

Response:

{
  "results": [
    {
      "entity_type": "PERSON",
      "start": 8,
      "end": 16,
      "score": 0.85,
      "text": "John Doe"
    },
    {
      "entity_type": "EMAIL_ADDRESS",
      "start": 20,
      "end": 36,
      "score": 1.0,
      "text": "john@example.com"
    },
    {
      "entity_type": "PHONE_NUMBER",
      "start": 45,
      "end": 57,
      "score": 0.95,
      "text": "555-123-4567"
    }
  ],
  "tokens_charged": 2
}

Token Cost: Base 1 token + 0.5 per entity found (rounded up)


Anonymize Text#

Apply anonymization operators to detected entities.

Endpoint: POST /api/presidio/anonymize

Request Body:

FieldTypeRequiredDescription
textstringYesOriginal text
analyzer_resultsobject[]YesResults from analyze endpoint
operatorsobjectNoPer-entity anonymization methods
languagestringNoISO 639-1 code

Operator Types:

TypeDescriptionParameters
replaceReplace with placeholdernew_value (default: <ENTITY_TYPE>)
redactRemove entirelyNone
hashSHA-256 hashhash_type: sha256 or sha512
maskPartial maskingmasking_char, chars_to_mask, from_end
encryptAES-256-GCM symmetric encryptionkey (16/24/32-char encryption key)
encrypt_asymRSA-4096 + AES-256-GCM asymmetric encryptionpublic_key_id (key pair ID) or public_key (PEM string)
keepKeep original valueNone

Example Request:

curl -X POST https://cloak.business/api/presidio/anonymize \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Contact John Doe at john@example.com",
    "analyzer_results": [
      {"entity_type": "PERSON", "start": 8, "end": 16, "score": 0.85},
      {"entity_type": "EMAIL_ADDRESS", "start": 20, "end": 36, "score": 1.0}
    ],
    "operators": {
      "PERSON": {"type": "replace", "new_value": "[REDACTED NAME]"},
      "EMAIL_ADDRESS": {"type": "hash", "hash_type": "sha256"}
    }
  }'

Response:

{
  "text": "Contact [REDACTED NAME] at 3c4a7b8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b",
  "items": [
    {
      "start": 8,
      "end": 23,
      "entity_type": "PERSON",
      "text": "[REDACTED NAME]",
      "operator": "replace"
    },
    {
      "start": 27,
      "end": 91,
      "entity_type": "EMAIL_ADDRESS",
      "text": "3c4a7b8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b",
      "operator": "hash"
    }
  ],
  "tokens_charged": 2
}

Token Cost: 1 token per entity anonymized


Batch Analyze#

Analyze multiple texts in a single request.

Endpoint: POST /api/presidio/batch

Plan Required: Basic or higher

Request Body:

FieldTypeRequiredDescription
textsstring[]YesArray of texts (max 50 items)
languagestringNoISO 639-1 code
entitiesstring[]NoEntity types to detect
score_thresholdnumberNoMinimum confidence

Example Request:

curl -X POST https://cloak.business/api/presidio/batch \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "texts": [
      "Contact John at john@test.com",
      "Call Jane at 555-987-6543"
    ],
    "language": "en"
  }'

Response:

{
  "results": [
    {
      "index": 0,
      "entities": [
        {"entity_type": "PERSON", "start": 8, "end": 12, "score": 0.85},
        {"entity_type": "EMAIL_ADDRESS", "start": 16, "end": 29, "score": 1.0}
      ]
    },
    {
      "index": 1,
      "entities": [
        {"entity_type": "PERSON", "start": 5, "end": 9, "score": 0.85},
        {"entity_type": "PHONE_NUMBER", "start": 13, "end": 25, "score": 0.95}
      ]
    }
  ],
  "tokens_charged": 4
}

Deanonymize Text#

Decrypt previously encrypted text using your encryption key (symmetric) or private key (asymmetric).

Endpoint: POST /api/presidio/deanonymize

Plan Required: Basic or higher

Request Body:

FieldTypeRequiredDescription
textstringYesAnonymized text with encrypted values
anonymizer_resultsobject[]YesResults from anonymize endpoint
deanonymizersobjectYesDecryption operators with keys

Deanonymizer Types:

TypeDescriptionParameters
decryptSymmetric AES decryptionkey (16/24/32-char encryption key)
decrypt_asymAsymmetric RSA-4096 decryptionprivate_key (PEM-formatted private key)

Example Request (Symmetric):

curl -X POST https://cloak.business/api/presidio/deanonymize \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Contact LzqYf_zJZ_7JYZUgUian... at email",
    "anonymizer_results": [
      {"start": 8, "end": 32, "entity_type": "PERSON", "operator": "encrypt"}
    ],
    "deanonymizers": {
      "PERSON": {"type": "decrypt", "key": "your-encryption-key-here"}
    }
  }'

Example Request (Asymmetric):

curl -X POST https://cloak.business/api/presidio/deanonymize \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "My email is GIszLbhC+eP04L7Z...== and phone is TKm1qial5As...==.",
    "anonymizer_results": [
      {"start": 12, "end": 742, "entity_type": "EMAIL_ADDRESS", "operator": "encrypt_asym"},
      {"start": 757, "end": 1487, "entity_type": "PHONE_NUMBER", "operator": "encrypt_asym"}
    ],
    "deanonymizers": {
      "DEFAULT": {"type": "decrypt_asym", "private_key": "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----"}
    }
  }'

Response:

{
  "text": "Contact John Doe at email",
  "items": [
    {
      "start": 8,
      "end": 16,
      "entity_type": "PERSON",
      "text": "John Doe"
    }
  ],
  "tokens_charged": 1
}

Error Responses:

StatusWhen
400Wrong key, wrong key type (public instead of private), or corrupted ciphertext
402Insufficient tokens

Asymmetric Key Endpoints#

Manage RSA-4096 key pairs for asymmetric encryption. Key pairs are per-user; the private key is encrypted server-side.

List Key Pairs#

GET /api/asymmetric-keys
Authorization: Bearer YOUR_API_KEY

Response:

{
  "keyPairs": [
    {
      "id": "cmmf6ow61001ofnssf739is4f",
      "keyName": "Production Keys",
      "fingerprint": "5fe079d73ba8d5d323bd84fbf914799e...",
      "algorithm": "RSA-4096",
      "isActive": true,
      "isZKWrapped": false,
      "hasPrivateKeyBackup": false,
      "usageCount": 42,
      "lastUsedAt": "2026-03-06T17:43:12.000Z",
      "createdAt": "2026-03-06T17:00:00.000Z",
      "updatedAt": "2026-03-06T17:43:12.000Z"
    }
  ]
}

Create Key Pair#

POST /api/asymmetric-keys
Authorization: Bearer YOUR_API_KEY
Content-Type: application/json

Request Body:

FieldTypeRequiredDescription
keyNamestringYesUnique name for the key pair
publicKeyPemstringYesRSA public key in PEM format
privateKeyPemstringYesRSA private key in PEM format (encrypted server-side before storage)

Response: 200 with { "keyPair": { ... } }

Error Responses:

StatusWhen
400Missing fields or invalid PEM format
409Key pair name already exists

Get Key Pair#

GET /api/asymmetric-keys/{id}
GET /api/asymmetric-keys/{id}?includePrivateKey=true

Without includePrivateKey, returns metadata only (no private key exposed). With includePrivateKey=true, includes the decrypted privateKeyPem field.

Get Public Key#

GET /api/asymmetric-keys/{id}/public

Returns only { "publicKeyPem": "-----BEGIN PUBLIC KEY-----\n..." }. Use this endpoint to share the public key with external apps.

Update Key Pair#

PUT /api/asymmetric-keys/{id}
Content-Type: application/json

Request Body (at least one field required):

FieldTypeDescription
keyNamestringNew name (must be unique)
isActivebooleanActivate or deactivate

Delete Key Pair#

DELETE /api/asymmetric-keys/{id}

Permanently deletes the key pair. For ZK users, requires x-session-key-hash header for session validation.

Response: 200 with { "success": true, "message": "Asymmetric key pair deleted" }


Image Endpoints#

Process Image#

Detect and optionally redact PII in images via OCR.

Endpoint: POST /api/presidio/image

Plan Required: Basic or higher

Content-Type: multipart/form-data

Form Fields:

FieldTypeRequiredDescription
filefileYesImage file (PNG, JPEG, BMP, TIFF)
modestringNoanalyze or redact (default: analyze)
languagestringNoOCR language (default: en)
entitiesstringNoJSON array of entity types
score_thresholdnumberNoMinimum confidence
fill_colorstringNoRedaction color: black, white, red, green, blue, gray

Limits:

  • Max file size: 10 MB
  • Max resolution: 25 megapixels
  • Supported formats: PNG, JPEG, BMP, TIFF

Example - Analyze Image:

curl -X POST https://cloak.business/api/presidio/image \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@document.png" \
  -F "mode=analyze" \
  -F "language=en"

Analyze Response:

{
  "entities": [
    {
      "entity_type": "PERSON",
      "score": 0.85,
      "left": 100,
      "top": 50,
      "width": 120,
      "height": 30,
      "text": "John Doe"
    },
    {
      "entity_type": "EMAIL_ADDRESS",
      "score": 1.0,
      "left": 100,
      "top": 90,
      "width": 200,
      "height": 30,
      "text": "john@example.com"
    }
  ],
  "entities_found": 2,
  "processing_time": 2.345,
  "tokens_charged": 3
}

Example - Redact Image:

curl -X POST https://cloak.business/api/presidio/image \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@document.png" \
  -F "mode=redact" \
  -F "fill_color=black" \
  --output redacted.png

Redact Response: Binary PNG image with redaction boxes applied.

OCR Languages Supported:

37 languages including: English, German, French, Spanish, Italian, Portuguese, Dutch, Polish, Russian, Chinese, Japanese, Korean, Arabic, Hindi, and more.


Account Endpoints#

Get Token Balance#

Check your current token balance.

Endpoint: GET /api/user/tokens

curl https://cloak.business/api/user/tokens \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "balance": 1500,
  "plan": "professional",
  "monthlyAllocation": 5000,
  "usedThisMonth": 3500
}

List Tokenization Sessions#

List active encryption sessions for deanonymization.

Endpoint: GET /api/user/sessions

curl https://cloak.business/api/user/sessions \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "sessions": [
    {
      "id": "sess_abc123",
      "createdAt": "2026-02-16T10:30:00Z",
      "expiresAt": "2026-02-17T10:30:00Z",
      "entityCount": 15
    }
  ]
}

Delete Session#

Delete a tokenization session.

Endpoint: DELETE /api/user/sessions/:sessionId

curl -X DELETE https://cloak.business/api/user/sessions/sess_abc123 \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "success": true,
  "message": "Session deleted"
}

Utility Endpoints#

Get Limits#

Retrieve current rate limits and request limits.

Endpoint: GET /api/presidio/limits

curl https://cloak.business/api/presidio/limits \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "maxTextLength": 500000,
  "maxEntitiesPerRequest": 50,
  "maxAdHocRecognizers": 50,
  "maxPatternsPerRecognizer": 10,
  "maxTotalPatterns": 200,
  "rateLimits": {
    "analyze": {"windowMs": 60000, "maxRequests": 60},
    "anonymize": {"windowMs": 60000, "maxRequests": 60},
    "image": {"windowMs": 60000, "maxRequests": 30}
  }
}

List Presets#

Get available entity presets.

Endpoint: GET /api/presets

curl https://cloak.business/api/presets \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "presets": [
    {
      "id": "preset_de",
      "name": "Deutschland - Vollständig",
      "entityCount": 41,
      "entities": ["DE_ID_CARD", "DE_PASSPORT", "DE_TAX_ID", "..."]
    },
    {
      "id": "preset_us",
      "name": "United States - Complete",
      "entityCount": 31,
      "entities": ["US_SSN", "US_PASSPORT", "US_DRIVER_LICENSE", "..."]
    }
  ]
}

List Entities#

Get all available entity types.

Endpoint: GET /api/presidio/entities

curl https://cloak.business/api/presidio/entities \
  -H "Authorization: Bearer YOUR_API_KEY"

Response:

{
  "entities": [
    {
      "type": "PERSON",
      "description": "Full person name",
      "detection": "nlp",
      "languages": ["en", "de", "fr", "..."]
    },
    {
      "type": "US_SSN",
      "description": "US Social Security Number",
      "detection": "pattern",
      "pattern": "###-##-####"
    }
  ],
  "totalCount": 390
}

Health Check#

Check service health status.

Endpoint: GET /api/health

curl https://cloak.business/api/health

Response:

{
  "status": "healthy",
  "version": "6.12.0",
  "services": {
    "analyzer": {"status": "healthy", "recognizers": 317},
    "anonymizer": {"status": "healthy"},
    "image": {"status": "healthy", "ocrLanguages": 37}
  }
}

Request & Response Examples#

Custom Pattern Recognizer#

Define ad-hoc recognizers for domain-specific entities:

curl -X POST https://cloak.business/api/presidio/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Employee ID: EMP-12345, Badge: B-9876",
    "ad_hoc_recognizers": [
      {
        "entity_type": "EMPLOYEE_ID",
        "patterns": [
          {"name": "emp_id", "regex": "EMP-\\d{5}", "score": 0.9}
        ],
        "context": ["employee", "staff", "worker"]
      },
      {
        "entity_type": "BADGE_NUMBER",
        "patterns": [
          {"name": "badge", "regex": "B-\\d{4}", "score": 0.85}
        ]
      }
    ]
  }'

Using Presets#

curl -X POST https://cloak.business/api/presidio/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "text": "Mein Name ist Hans Müller, Steuer-ID 12 345 678 901",
    "language": "de",
    "preset": "Deutschland - Vollständig"
  }'

Full Anonymization Workflow#

# Step 1: Analyze
ANALYZE_RESULT=$(curl -s -X POST https://cloak.business/api/presidio/analyze \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "Contact John at john@test.com", "language": "en"}')

# Step 2: Anonymize with results
curl -X POST https://cloak.business/api/presidio/anonymize \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"text\": \"Contact John at john@test.com\",
    \"analyzer_results\": $(echo $ANALYZE_RESULT | jq '.results'),
    \"operators\": {
      \"PERSON\": {\"type\": \"replace\"},
      \"EMAIL_ADDRESS\": {\"type\": \"hash\", \"hash_type\": \"sha256\"}
    }
  }"

SDKs & Libraries#

We provide official SDKs for JavaScript/TypeScript and Python with full type safety, automatic retry logic, and client-side encryption support.

JavaScript/TypeScript SDK#

npm install @cloak-business/sdk
# or
yarn add @cloak-business/sdk
import { CloakClient } from '@cloak-business/sdk';

const client = new CloakClient({ apiKey: 'YOUR_API_KEY' });

// Analyze text for PII
const analysis = await client.analyze({
  text: 'Contact John at john@example.com',
  language: 'en'
});

// Anonymize
const result = await client.anonymize({
  text: 'Contact John at john@example.com',
  analyzerResults: analysis.results,
  operators: {
    PERSON: { type: 'replace', new_value: '[REDACTED]' },
    EMAIL_ADDRESS: { type: 'hash', hash_type: 'sha256' }
  }
});

Python SDK#

pip install cloak-business
# For client-side encryption:
pip install cloak-business[crypto]
from cloak_business import CloakClient

client = CloakClient(api_key="YOUR_API_KEY")

# Analyze text for PII
analysis = client.analyze(text="Contact John at john@example.com")

# Anonymize
result = client.anonymize(
    text="Contact John at john@example.com",
    analyzer_results=analysis.results,
    operators={
        "PERSON": {"type": "replace", "new_value": "[REDACTED]"},
        "EMAIL_ADDRESS": {"type": "hash", "hash_type": "sha256"}
    }
)

Client-Side Encryption#

Both SDKs include ClientCrypto modules for zero-knowledge encryption where keys never leave your device:

import { ClientCrypto } from '@cloak-business/sdk';

const key = await ClientCrypto.generateKey();
const encrypted = await ClientCrypto.encrypt(key, 'sensitive data');
const decrypted = await ClientCrypto.decrypt(key, encrypted);

See the SDK Reference for complete documentation including error handling, batch processing, and more.

cURL#

All examples in this documentation use cURL. Replace YOUR_API_KEY with your actual API key.



Document maintained by cloak.business Contact: support@cloak.business