PvP Logs API v3

One match identity.
Every trusted perspective.

Build on canonical World of Warcraft PvP matches, character history, tactical replay and evidence confidence.

OpenAPI 3.1 documentCreate an access key
QUICKSTART

Submit an observation

Create a revocable key in your account, then send a protocol v2 observation with a unique idempotency key.

curl -X POST https://your-domain/api/v3/observations \
  -H "Authorization: Bearer pvp_••••••" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 0c8d8b31-…" \
  -H "X-PvPLogs-Agent-Version: 2.0.0" \
  --data-binary @observation.json
Upload scope is free.

Free accounts can create agent keys. Pro adds read API access and higher quotas.

HTTP API

Core endpoints

GET/api/v3/characters?query=Horror-Hellscream

Search indexed characters

GET/api/v3/characters/us/hellscream/horror

Profile and entitled history

GET/api/v3/matches?limit=25&cursor=…

Canonical match feed

GET/api/v3/matches/{matchId}

Match and base tactical replay

POST/api/v3/observations

Authenticated agent ingestion

GET/api/v3/me

Account and entitlements

AUTHENTICATION

Keys identify accountable upload sources

Secrets are shown once and stored only as SHA-256 hashes. Keys are scoped, rate-limited and revocable. Browser account actions use the signed-in session and same-origin checks.

Free upload key

Scope: upload
12 observations per minute

Pro API key

Scopes: upload,read
10,000 read requests per day

DESKTOP AGENT

Send one compact perspective through API v3

New agents post only to /api/v3/observations. Each request carries a Bearer key, a stable content-derived Idempotency-Key, the agent version header, and a body no larger than 8 MB. Region, realm and observing player ID are explicit so character indexing never guesses the observer identity.

Replay placement

Write compact telemetry to match.tacticalReplay. The server temporarily accepts the older match.analysis.tacticalReplay shape during migration.

Safe retries

Persist pending jobs, honor Retry-After, retry network/429/5xx responses with jitter, and reuse the same key for the same bytes.

API v2 is retired.

Legacy v2 match and character routes return 410 Gone. Existing agents must migrate before they can upload to this website.

DATA INTEGRITY

Corroborated, not magically cheat-proof

A desktop client can never prove that every byte is truthful. PvP Logs instead binds evidence to authenticated sources, keeps raw observations immutable, validates physical and structural constraints, and builds field-level confidence from independent agreement.

  1. 01
    Server-derived source identity

    Submitted source.id values never decide independence. One account counts as one source.

  2. 02
    Serialized canonical merge

    A D1-backed lock prevents concurrent uploads from overwriting one another. Each merge creates an immutable revision.

  3. 03
    Visible disagreement

    Winner, roster, deaths, tracks and copied evidence affect the contested status and confidence score.

  4. 04
    One canonical match

    Arena, bracket, exact roster and start window connect uploads to one shared match ID.

ANALYSIS METHOD

Scores carry coverage, confidence and a version

PvP Logs scores only when at least two recorded telemetry domains are available. Missing health or position data is marked unavailable instead of receiving a favorable default. Advanced fields stay on the server until the current account is entitled to them.

Current version: 2026-07-19.4

Output, activity, control, survival and positioning are reweighted over the evidence actually present. The repository includes the complete methodology and limitations.

RELIABILITY

Stable errors and safe retries

Every API response includes a request ID. Uploads require Idempotency-Key; retrying the same bytes returns the original observation, while reusing a key for different bytes returns 409. The complete request is limited to 8 MB, 50,000 track samples, 25,000 replay events and six independent contributions per canonical match.

{
  "status": "error",
  "requestId": "…",
  "error": {
    "code": "invalid-observation",
    "message": "protocolVersion 2 is required"
  }
}