# Proof of Human — partner integration guide

> Verify a PoH credentialed WAV by itself, retain the legacy audio + .poh fallback, and monitor the integration without copying proof data into telemetry.

Production base URL: `https://api.proofofhuman.fm/v1`
Beta (integration testing) base URL: `https://beta.api.proofofhuman.fm/v1`

Integrate on beta first: it runs the same contract and authentication as production on isolated
pre-production infrastructure — separate API keys, a separate registry, disposable test proofs.
Beta and production keys are different secrets and never interchangeable; pass the beta base URL
via `new PoHClient({ apiKey, baseUrl })` in staging and switch to the production URL and key at
go-live.

- [API reference](/developers)
- [OpenAPI](https://proofofhuman.fm/openapi.json)
- [TypeScript SDK](https://www.npmjs.com/package/@proof-of-human/ts-sdk)
- [Changelog](/developers/changelog)

## Core flow

Keep `POH_API_KEY` in a server-side secret manager. Never ship it in browser code or log it.

```ts
import { readFile } from "node:fs/promises";
import { PoHClient } from "@proof-of-human/ts-sdk";

const poh = new PoHClient({ apiKey: process.env.POH_API_KEY! });
const upload = await poh.createUpload();
const bytes = await readFile("credentialed-song.wav");
const form = new FormData();
for (const [key, value] of Object.entries(upload.fields)) form.append(key, value);
form.append("file", new Blob([new Uint8Array(bytes)], { type: "audio/wav" }), "credentialed-song.wav");
const posted = await fetch(upload.url, { method: "POST", body: form });
if (!posted.ok) throw new Error(`upload failed: ${posted.status}`);

const result = await poh.verify({ uploadId: upload.uploadId });
```

Legacy fallback: base64 the separate `.poh` and call `verify({ uploadId, poh })`. One-file delivery is currently WAV/BWF and accepts up to 65 MiB in a verification slot. AIFF, CAF, MP3, and M4A use the legacy pair.

## Verdicts

- `valid` — signature, registry record, and exact audio binding passed.
- `audioChanged` — legacy audio does not match the sidecar.
- `tampered` — proof, embedded identity, or signature changed.
- `unregistered` — not a registered PoH-issued credential.
- `unreadable` — no readable proof, or embedded hard binding failed.
- `local_seal` — an artist-device seal was never registered with PoH.

`classification`, `grade`, and `interpretation` are report-only and do not change credential validity. A valid proof is not an “AI-free” certificate.

## Monitoring

Record HTTP status, latency, `X-Request-Id`, `X-RateLimit-*`, and `Retry-After` in your APM. Never log the key, audio, proof, presigned fields, proof IDs in URLs, or response bodies.

- Probe authenticated `GET /partner/usage?days=1` every five minutes.
- Alert on sustained 5xx responses, latency regression, repeated 429s, and low quota headroom.
- Include request ID and UTC time in every support report.

Current embedded assets are **C2PA · PoH verified**. Public Trust List / timestamp enrollment is not complete, so `publiclyTrusted` correctly remains false.

---

More: [llms.txt](https://proofofhuman.fm/llms.txt) · [sitemap](https://proofofhuman.fm/sitemap.md)
