Skip to main content
PHOTOTOLOGY

Build photo intelligence into your product.

Save Time. Save Tokens. Save Truth.

Composable AI analysis lenses. Deterministic Zod-validated JSON. Evidence chains on every conclusion. One API call.

Paste this. Get structured context back.

The sandbox key pt_test_sandbox returns fixture data instantly. Use it to shape integrations before signup; the response is the same fake payload every call.

curl -X POST https://api.phototology.com/v1/analyze \
  -H "Authorization: Bearer pt_test_sandbox" \
  -H "Content-Type: application/json" \
  -d '{"imageUrl":"https://example.com/photo.jpg","preset":"full-analysis"}'

Test keys return fixture data instantly. Sign up for a live key when you are ready to analyze real photos.

Four ways in. Same engine.

MCP Server

Claude Desktop / Claude Code

Add Phototology as a tool. Your agent can analyze photos without a vision model.

npx @phototology/mcp

Claude Desktop config:

{
  "mcpServers": {
    "phototology": {
      "command": "npx",
      "args": ["-y", "@phototology/mcp"],
      "env": {
        "PHOTOTOLOGY_API_KEY": "pt_test_sandbox"
      }
    }
  }
}
TypeScript SDK

npm install @phototology/sdk

Typed client with built-in retries, error hierarchy, and streaming support.

import { PhototologyClient } from '@phototology/sdk';

const pt = new PhototologyClient({ apiKey: 'pt_test_sandbox' });
const result = await pt.analyze({
  imageUrl: 'https://example.com/photo.jpg',
  modules: ['dating', 'entities'],
});

View on npm →

REST API

POST /v1/analyze

Send a photo with a curated stack or your own lens list. Get structured JSON back. Works from any language.

POST https://api.phototology.com/v1/analyze
Authorization: Bearer pt_test_sandbox
Content-Type: application/json

{
  "imageUrl": "https://example.com/photo.jpg",
  "preset": "full-analysis"
}
OpenAPI 3.1

Interactive API Docs

Full OpenAPI spec with request/response schemas. Try endpoints directly from the browser.

GET https://api.phototology.com/v1/docs
GET https://api.phototology.com/v1/openapi.json

Open API docs →

Every response. Every surface. Same envelope.

Zod-validated. Deterministic. The shape never changes between lenses, stacks, or SDK versions. (The concept words are lens and stack; on the wire, the API request body uses the field names modules and preset for back-compat with existing SDK callers. Both naming conventions refer to the same units.)

{
  "id": "an_...",
  "object": "analysis",
  "schemaVersion": "2.1.0",
  "outputSchema": "photo",
  "createdAt": "2026-04-29T12:00:00Z",
  "output": { /* flat-keyed fields per requested lenses */ },
  "usage": {
    "inputTokens": 1847,
    "outputTokens": 412,
    "totalTokens": 2259,
    "modulesUsed": ["dating", "entities", "describe"],
    "creditsCharged": 3
  },
  "warnings": [],
  "meta": {
    "processingTimeMs": 2340,
    "provider": "gemini",
    "model": "gemini-3.1-flash-lite",
    "vendor": "google",
    "promptHash": "sha256:...",
    "requestId": "req_abc123",
    "ai_generated": true
  }
}

output

Lens results keyed by field name. Only fields owned by the lenses you request appear in the output. (Wire field: modules.)

usage

Token counts, cost estimate, the lenses that ran, and the credits charged. Use this for billing reconciliation.

meta

Processing time, provider, prompt hash for reproducibility, and a unique request ID for support.

Built for agents. Every error tells you what to do.

Every error response includes a retryable boolean. Your agent never has to guess.

{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded. Retry after 2 seconds.",
    "retryable": true,
    "requestId": "req_abc123"
  }
}
CodeMeaningRetryable
400Bad request. Invalid lenses, missing image, or malformed body.No
401Invalid or missing API key.No
402Insufficient credits. The body includes a credits breakdown (needed vs available). Buy credits or wait.No
422Image fetch failed or unsupported format (unreachable URL, bad type, too large).No
429Rate limit exceeded. Check the Retry-After header.Yes
500Internal server error. Something broke on our side.Yes
502Upstream provider error (vision model unavailable).Yes

Rate limit: 600 requests per minute on authenticated keys. The public sandbox key (anonymous, no account) is capped at 2 requests per minute and 10 per day per IP. The Retry-After header is included on all 429 responses.

$0.01/lens, flat. 5,000 free credits to start.

Full analysis under $0.20/photo. Most use cases need 2-4 lenses. Re-analyzing a photo only bills lenses you have not run before. Lookups are free.

View pricing

Photo in. Context out.

5,000 free credits to start. No subscription. Sandbox key works right now.

Get your API key

or read the full API docs →

Developers | Phototology - Photo Intelligence API | Phototology