Developers
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.
Try It Now
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.
Integration Surfaces
Four ways in. Same engine.
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"
}
}
}
}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'],
});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"
}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
Response Shape
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.
Error Handling
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"
}
}| Code | Meaning | Retryable |
|---|---|---|
400 | Bad request. Invalid lenses, missing image, or malformed body. | No |
401 | Invalid or missing API key. | No |
402 | Insufficient credits. The body includes a credits breakdown (needed vs available). Buy credits or wait. | No |
422 | Image fetch failed or unsupported format (unreachable URL, bad type, too large). | No |
429 | Rate limit exceeded. Check the Retry-After header. | Yes |
500 | Internal server error. Something broke on our side. | Yes |
502 | Upstream 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 pricingPhoto in. Context out.
5,000 free credits to start. No subscription. Sandbox key works right now.
Get your API key