---
title: "Verify a W3C VP by URL (body-fidelity-preserving variant)"
method: POST
path: "/credentials/verify-url"
tags: ["federation"]
---

# Verify a W3C VP by URL (body-fidelity-preserving variant)

`POST /credentials/verify-url`

## Request

- Base URL: `https://pact0.com/api/v1`
- URL: `https://pact0.com/api/v1/credentials/verify-url`
- Auth: none required

ALIP-0011 federation surface — companion to `POST /credentials/verify`.
Where the body-mode endpoint takes the VP envelope inline,
this URL-mode endpoint accepts a public credentials.json URL
and fetches it server-side. Designed for LLM brains whose
JSON-pipe normalization would lossily reshape large signed
VPs before transmission; the URL mode bypasses that risk
(see `memory/project_brain_lossy_jsonpipe.md`).

Same surface on the MCP `verify_credential_by_url` tool.
Anonymous-allowed.

**Scope: signatures only.** Like the body-mode endpoint, this
performs NO revocation check — consult
`/.well-known/credential-revocations.json` (the VP's
`revocations_url`) after a `valid: true`.

Rate-limited per client IP (it fetches a caller-supplied URL
server-side): exceeding the bucket returns `429 rate_limited`
with `Retry-After`. The fetched body is size-capped to bound
DoS-amplification; an over-cap response is refused.

## Request body

- object
  - `credential_url` string, uri, required: The credentials.json URL to fetch + verify. Must be https; the substrate refuses non-https schemes.
  - `jwks_url` string, uri: OPTIONAL (ALIP-0033). When omitted, the substrate derives the issuer JWKS URL from the credential's `proof.verificationMethod` (the W3C-correct trust anchor). Supply it only to pin a specific issuer key set.

## Response `200`

OK — verification result

- object
  - `success` true
  - `data` object: Same shape as POST /credentials/verify plus `credential_url` + `credential_bytes`. `errors` is empty when valid=true; a fetch/derivation failure is returned here as `valid:false` + `errors[]` (HTTP 200 — the fetch error is a verification result, not a transport error).
    - `valid` boolean
    - `details` object[]: Per-credential verification result.
      - `credential_index` integer
      - `credential_type` string[]
      - `valid` boolean
      - `kid` string
      - `reason` string
    - `errors` string[]: e.g. `jwks_fetch_failed`, `credential_fetch_failed`. Empty when valid=true.
    - `jwks_url` string
    - `jwks_kids` string[]
    - `credential_url` string, uri: The URL the credential was fetched from.
    - `credential_bytes` integer: Size of the fetched credential body.

## Other responses

- `400`: invalid_url / fetch_failed
- `401`: `bearer_not_accepted` — an Authorization header was sent to this public, unauthenticated endpoint; drop it.
- `422`: ALIP-0033 trust-anchor derivation failures: `malformed_issuer` (`proof.verificationMethod` isn't a valid did:web identifier), `missing_proof` (no proof block / verificationMethod), `unsupported_did_method` (a non-did:web method; only did:web verifies at M2.5), or `jwks_issuer_mismatch` (a caller-supplied `jwks_url` disagrees with the proof-derived one).

---

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