Integration guide · v1 · staging-api.storyprotocol.net
Send a webhook. That's the integration.
Trace stores a provider-normalized Trace Schema v1.0 record per asset. The contributing app POSTs batches of registrations and metadata updates; Trace handles indexing, search, and onchain registration on the app's behalf.
Base URL · https://staging-api.storyprotocol.net
Headers
Auth & provider scope
Every write request must include three headers. The API key must be bound to the provider sent in X-Provider.
X-API-Key: <Kled staging key> X-Provider: kled X-Batch-Id: <stable batch id>
Read endpoints accept the same API key; authorization is not provider-scoped. provider can be sent as an optional filter on the search endpoint.
Write API
Register initial data IDs
Use this for initial backlog and live registration batches. The request body is a JSON array of records.
POST /webhook/v1/data-audit/data-ids:batch Content-Type: application/json X-API-Key: <Kled staging key> X-Provider: kled X-Batch-Id: kled-dataids-000001
[
{
"data_id": "11111111-1111-4111-8111-111111111111",
"source_record_id": "kmf_8a9c2e7d4b1f0e23",
"initial_metadata_root": "sha256:<canonical-trace-schema-v1-json>",
"initial_metadata_json": {
"schema_version": "trace-v1.0",
"file": {
"content_sha256": "b1946ac92492d2347c6235b4d2611184",
"mime_type": "video/mp4",
"media_category": "video",
"size_bytes": 123456,
"hashes": {
"phash64": "facebeef01234567",
"dhash64": "1b9072d44a8be3c1",
"ahash64": "ff7e3c1a90d5e8c2",
"keyframe_phashes": ["0011223344556677"]
},
"behavior": {
"captured_via": "ios_native_camera",
"uploaded_via": "ios_app",
"upload_session_kind": "gallery_pick"
}
},
"file_specific": {
"base": { "motion": { "speed_bucket": "stationary" } },
"video": { "duration_ms": 120000, "width": 1920, "height": 1080 }
},
"user": {
"source_user_id": "kup_123",
"kyc_status": "verified",
"kyc_country": "US",
"tos_accepted": {
"version": "2026-05-20",
"accepted_at": "2026-05-13T00:00:00Z"
},
"privacy_policy_accepted": {
"version": "2026-05-20",
"accepted_at": "2026-05-13T00:00:00Z"
}
},
"app": {
"platform_name": "kled.ai",
"legal_entity": "Nitrility Inc. (Delaware, USA)",
"active_tos": { "version": "2026-05-20", "url": "https://kled.ai/terms" },
"active_privacy_policy": { "version": "2026-05-20", "url": "https://kled.ai/privacy" }
},
"timestamps": {
"occurred_at": "2026-05-13T00:00:00Z",
"uploaded_at": "2026-05-13T00:00:00Z"
},
"attestation": {
"payload_hash": "sha256:<canonical-trace-schema-v1-json>",
"key_id": "kled-verify-2026-q1",
"key_url": "https://kled.ai/.well-known/verification-keys.json",
"signed_at_utc": "2026-05-13T00:00:02Z"
},
"provider_payload": {
"media_id_public": "kmf_8a9c2e7d4b1f0e23"
}
},
"occurred_at": "2026-05-13T00:00:00Z"
}
]initial_metadata_rootshould be the provider's deterministic hash of the canonical Trace Schema v1.0 metadata JSON. In the current staging API, Trace stores this value as submitted; hash verification against initial_metadata_json is not enforced yet.
Write API
Submit metadata updates
Later corrections or mutable metadata changes go here. seq must be between 1 and 20 for the same data_id.
POST /webhook/v1/data-audit/metadata-updates:batch Content-Type: application/json X-API-Key: <Kled staging key> X-Provider: kled X-Batch-Id: kled-metadata-000001
[
{
"data_id": "11111111-1111-4111-8111-111111111111",
"seq": 1,
"prev_metadata_root": "sha256:<previous>",
"metadata_root": "sha256:<new>",
"metadata_json": {
"schema_version": "trace-v1.0",
"user": { "source_user_id": "kup_123", "kyc_status": "unverified" },
"app": { "platform_name": "kled.ai" },
"provider_payload": {
"media_id_public": "kmf_8a9c2e7d4b1f0e23",
"reason": "kyc_status_changed"
}
},
"occurred_at": "2026-05-13T00:00:01Z"
}
]Optional NDJSON variants exist for large backlog tooling at /webhook/v1/data-audit/data-ids:batch-ndjson and /webhook/v1/data-audit/metadata-updates:batch-ndjson. Both require Content-Encoding: gzip.
Read API
Look up & search
Read endpoints are keyed by Story data_id. Provider is returned as a field and can be used as an optional filter or searched directly.
GET /api/v1/data-audit/data-ids/<data_id> GET /api/v1/data-audit/data-ids/<data_id>/metadatas GET /api/v1/data-audit/search?field=file.media_category&value=video&limit=100
Search
Indexed (exact-match) fields
- — provider
- — source_record_id
- — media_id_public
- — file.content_sha256 (asset_hash alias)
- — file.mime_type
- — file.media_category
- — collection_id
- — customer_id
- — task_id
- — user.source_user_id
- — user.kyc_status
- — user.kyc_country
- — contributor.geo_region
- — tos_hash
- — privacy_policy_hash
Perceptual hashes (phash64, dhash64, ahash64, keyframe_phashes) and md5 may be preserved in payloads, but they are not indexed.
Constraints
Limits & retry behavior
Max request body: 25 MiB Max serialized record: 350 KiB Max metadata updates per data_id: 100
- — Retry
502 / 503 / 504, network timeouts, and429with exponential backoff + jitter. - — Do not retry validation/auth
4xxuntil fixed. - — Keep
data_id, request body, andX-Batch-Idstable across retries. - — The write path is idempotent for the same
data_id, event key, and event hash. - — Same
data_id+ event key submitted with different metadata is treated as a conflict and rejected.