Skip to content

REST API

C2PA signing, verification, org identity, and usage. Base URL: https://api.krusade.dev
Errors follow RFC 7807 problem+json with a machine-readable code field. OpenAPI spec: docs/openapi.yaml. Deep dives: Signing API, Public verify, What is C2PA?. Watermark routes: Invisible watermarking.
POST/api/v1/signBearer krsd_* or session

Stamp media with a C2PA Content Credential plus optional standards assertions (IPTC, EXIF, CAWG, PLUS, XMP, Web3, author). Add ?manifest=sidecar for a ZIP of the unmodified asset and a detached .c2pa manifest.

Request
multipart/form-data
file=<binary> (required)
author=Jane Doe
standards=iptc,training_mining,plus
iptc={"creator":["Jane Doe"]}
Response
200 — signed asset bytes (embedded)
200 — application/zip (?manifest=sidecar)
402 — insufficient_credits
415 — validation_failed (unsupported type)
POST/api/v1/sign/batchBearer krsd_* or session

Sign up to 25 files in one request. Returns a ZIP archive with signed assets and a JSON status manifest. Live on the API, CLI, and SDKs.

Request
multipart/form-data
files=<binary> (repeat up to 25)
Response
200 — application/zip
POST/api/v1/verifyBearer krsd_* or session

Verify a file's C2PA manifest. Same report shape as public verify, but callable with a developer key. Optional manifest part for sidecar credentials.

Request
multipart/form-data
file=<binary> (required)
manifest=<binary> (optional detached .c2pa)
Response
{
  "status": "valid",
  "trusted": true,
  "issuer": "Krusade",
  "assertions": [
    { "label": "stds.schema-org.CreativeWork", "data": { "author": "Jane Doe" } }
  ]
}

Public, accountless verification. Rate limited to 30 requests per minute per client IP. Unsigned files return 200 with status: no_credentials.

Request
multipart/form-data
file=<binary> (required)
Response
{
  "status": "valid" | "invalid" | "no_credentials",
  "trusted": true,
  "issuer": "Krusade",
  "signed_at": { "time": "2026-07-05T00:00:00Z", "timestamped": true }
}
POST/api/verifyPublic

Stable back-compat alias of POST /api/v1/public/verify. Identical behaviour.

GET/api/standardsPublic

Public registry of supported standards (name, label, display name, kind). Drives the standards selector.

Response
[{ "name": "iptc", "label": "stds.iptc.photo-metadata", "display_name": "IPTC", "kind": "metadata" }]
GET/api/v1/usageBearer krsd_* or session

Signs this month, free-tier usage, credit balance, and Team included-sign pool when applicable.

Response
{
  "signs_this_month": 7,
  "free_signs_used": 5,
  "free_signs_lifetime_limit": 1000,
  "credit_balance": 198
}
GET/api/v1/signaturesBearer krsd_* or session

Paginated org signature history for owners and members. Query params: limit, cursor.

GET/api/org/{id}Public

Public organization details (name, domain, is_verified).

POST/api/orgSession

Register your organization under your account. Requires an active Team subscription.

List org verify webhook endpoints (secrets redacted). Team owner/admin.

Register an HTTPS verify webhook. Secret returned once. Team owner/admin.

Update webhook URL. Team owner/admin.

Deactivate a webhook. Team owner/admin.

Rotate HMAC secret (returned once). Team owner/admin.

POST/api/v1/billing/chargeSession

Buy credits via Stripe. Requires Idempotency-Key header.

GET/api/v1/billing/transactionsSession

Credit ledger — purchases and per-sign spends.