---
title: "List every piece of metadata a document or image carries"
method: POST
path: "/api/v1/metadata"
tags: ["Inspect"]
---

# List every piece of metadata a document or image carries

`POST /api/v1/metadata`

## Request

- Base URL: `https://tamperlens.com` (the document declares no server; this is the origin it was published from)
- URL: `https://tamperlens.com/api/v1/metadata`
- Auth: none declared

Accepts multipart/form-data with a `file` field, or a raw body. Returns a MetadataReport: every key the file carries, grouped by the container it came from, with the raw stored form beside the decoded one.

**What you get, by medium.**

- **PDF**: the complete Info dictionary (not just the five fields the signal families read: `Author`, `Subject`, `Keywords` and any custom keys a pipeline invented are all listed), every XMP property, and plain structural facts (pages, revisions, encryption, signatures, fonts).
- **Images** (EXIF split by directory (IFD0, Exif, GPS, IFD1), the thumbnail's own metadata stays distinguishable from the photograph's), decoded GPS coordinates, PNG text chunks, XMP, and the containers present but not enumerated (IPTC, ICC, MakerNote, C2PA) named rather than silently omitted. JPEG, PNG, WebP, HEIC/HEIF and AVIF are all read the same way: a HEIC off an iPhone carries the same EXIF a JPEG does, in a different container.
- **Office**: core properties, application properties, custom properties, and **the EXIF of every image embedded in the package**. A photograph pasted into a `.docx` keeps the coordinates the camera wrote; that is usually the most surprising thing in the report.

**`personal`** collects the entries that identify a person, a device or a place, names, serial numbers, software, locations, as a copy, so the full grouped list stays complete. **`gps`** repeats a decoded coordinate pair as numbers, so a client need not parse its own report back into them.

**Each entry carries up to three forms of one fact.** `value` is display-ready and always English; `raw` is what the file stores, present only when decoding changed it (an EXIF rational, a PDF `D:` date); and `code` appears when `value` is a decoded ENUMERATION rather than data. `exif.Flash.16` for a `Flash` of 16, which reads "Did not fire, flash suppressed". The code is a translation key, the same shape `signals[].message` uses: `value` stays byte-identical for every consumer that ignores it, and a client with a dictionary can render another language. An entry with no `code` is data out of the file and must not be translated.

**This is not an inspection.** There are no signals, no risk score and no verdict here; use `POST /inspect` for those. And there is no way to get a modified file back: Tamperlens reads documents and never writes them.

**Cost.** One document against the monthly quota. Works anonymously, like the free checker.

## Response `200`

Default Response

- object

## Other responses

- `400`: `no_file`: a multipart request with no `file` part. `malformed_multipart`: the multipart body could not be parsed (a broken or missing boundary, a body cut off mid-part). Message: "The multipart body could not be parsed. Check the boundary and send the document as one file part."
- `413`: `file_too_large` (with `maxMb`): the body or the multipart file is over the upload cap. `too_many_parts`: the multipart body has more fields, files or parts than an upload needs. Message: "The multipart body has more fields, files or parts than an upload needs. Send the document as one file part with at most a few fields."

---

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