---
title: "Analyze a photo (v2)"
method: POST
path: "/v2/analyze"
tags: ["Analysis"]
---

# Analyze a photo (v2)

`POST /v2/analyze`

## Request

- Base URL: `https://api.phototology.com`
- URL: `https://api.phototology.com/v2/analyze`
- Auth: HTTP bearer

Registry v2 analyze endpoint. Superset of `/v1/analyze` with bespoke extraction (`extract.prompt` / `extract.schema` / `extract.schemaId`).

### Delta billing
The registry projection tracks which lenses have already been analyzed for each `(userId, sha256)` photo. By default only newly-requested lenses are billed; previously-analyzed lenses are served from the projection at zero cost.

Set `refresh: true` to force every requested lens to re-run (full billing). Bespoke extraction modes (`extract.*`) always bypass the registry path and bill normally: 5 credits per call regardless of cache state.

### Bespoke extraction
Pass `extract.prompt` (natural-language) for AI-generated schemas, `extract.schema` for an inline JSON Schema, or `extract.schemaId` for a previously-saved schema. Exactly one of the three is required when using `extract`.

## Request body

- object
  - `imageUrl` string, uri
  - `imageBase64` string
  - `images` object[]
    - `url` string, uri
    - `base64` string
  - `preset` string
  - `modules` string[]
  - `modulesAdd` string[]
  - `modulesRemove` string[]
  - `moduleOptions` object
  - `context` object
    - `knownPeople` object[]
      - `name` string, required
      - `birthYear` integer
      - `deathYear` integer
      - `role` string
    - `vehicle` object
      - `vin` string
      - `mileage` integer
      - `year` integer
      - `make` string
      - `model` string
    - `customInstructions` string
  - `options` object
    - `includeEmbedding` boolean
    - `includeFingerprint` boolean
  - `extract` object
    - `prompt` string
    - `schema` object
      - `type` 'object', required
      - `properties` object, required
      - `required` string[]
    - `schemaId` string
  - `refresh` boolean

## Response `200`

Analysis completed successfully. Response shape matches `/v1/analyze`; bespoke output appears under `output.bespoke`. On a full cache hit, `meta.cacheHit` is `true` and `usage.creditsCharged` is `0`. A content-safety block returns **200** with `output.moderation.safe: false` (same contract as `/v1/analyze`; see its `moderation-block` example).

- object
  - `id` string, required
  - `object` 'analysis', required
  - `livemode` boolean, required
  - `schemaVersion` string, required
  - `createdAt` string, required
  - `output` object, required
  - `outputSchema` 'photo' | 'vehicle', required
  - `usage` object, required
    - `inputTokens` number, required
    - `outputTokens` number, required
    - `totalTokens` number, required
    - `modulesUsed` string[], required
    - `creditsCharged` integer
    - `creditsSaved` integer
    - `usd` object
      - `charged` string, required
      - `saved` string, required
  - `warnings` string[], required
  - `meta` object, required
    - `processingTimeMs` number, required
    - `provider` string, required
    - `promptHash` string, nullable, required
    - `requestId` string, required
    - `cacheHit` boolean
    - `ai_generated` boolean, required
    - `model` string, required
    - `vendor` 'google' | 'openai' | 'anthropic', required
  - `embedding` number[]
  - `fingerprint` object
    - `pHash` string, required
    - `dHash` string, required
    - `sha256` string, required
    - `pixelsSha256` string
    - `pdq` object
      - `hash` string, required
      - `quality` integer, required
      - `variants` string[], required
    - `iscc` string
  - `receipts` object[]
    - `payload` object, required
      - `type` 'phototology.receipt', required
      - `version` 1, required
      - `id` string, required
      - `livemode` boolean, required
      - `issuer` 'https://phototology.com', required
      - `keyId` string, required
      - `subject` object, required
        - `bytesSha256` string, required
        - `pixelsSha256` string
        - `pHash` string, required
        - `dHash` string, required
        - `pdq` object
          - `hash` string, required
          - `quality` number, required
        - `iscc` string
      - `analysis` object, required
        - `requestId` string, required
        - `lenses` object[], required
          - `id` string, required
          - `version` string, required
          - `outputSha256` string, required
        - `provider` string, required
        - `model` string, nullable, required
        - `modelVersion` string, nullable, required
        - `outputSha256` string, required
        - `analyzedAt` string, required
      - `firstSeenAt` string, required
      - `credentials` object, required
        - `status` string, required
      - `registry` object, required
        - `url` string, required
    - `signature` string, required
    - `timestamp` object, required
      - `status` 'ok' | 'pending' | 'unavailable', required
      - `tsa` string
      - `token` string
      - `time` string
  - `credentials` object
    - `status` 'none' | 'invalid' | 'valid' | 'trusted' | 'unread', required
    - `aiGenerated` boolean, nullable, required
    - `signer` object, nullable, required
      - `name` string, required
      - `issuer` string, required
    - `captureDevice` string, nullable, required
    - `signedAt` string, nullable, required
    - `trustList` 'c2pa' | 'legacy', nullable, required
    - `assertions` string[], required
    - `note` string, required

## Other responses

- `400`: Request validation failed.
- `401`: Missing or invalid API key.
- `402`: Insufficient credits. Same shape as `/v1/analyze`: `error.credits` carries `needed`, `community`, `purchased`, `total`, and `resetsInDays`. Route sets `Cache-Control: no-store, private`.
- `404`: Saved bespoke schema not found (only emitted when `extract.schemaId` is used).
- `422`: Image fetch failed or payload invalid.
- `429`: Rate limit exceeded.
- `502`: Upstream AI provider unavailable, returned an error, or bespoke extraction failed at the provider.

---

[API](https://skmtc.dev/phototology/apis/phototology-api.md) · [All operations](https://skmtc.dev/phototology/apis/phototology-api/llms.txt) · [OpenAPI document](https://skmtc.dev/phototology/apis/phototology-api/revisions/3cb0fc707b63?raw)
