Developer Reference
Integrate Kernel Security signing and verification into your application using API keys.
Signing and verification in 30 seconds.
Sign once.
Let anyone check.
It starts with your content.
The Kernel Security API allows your application to programmatically sign media files with cryptographic watermarks and verify their signature. All requests must be authenticated with an API key issued from your organization's admin panel.
https://api.kernelsecurity.tech
Requests that upload a file (sign and verify) go to a separate host, built for large files:
https://transfer.kernelsecurity.tech
| Endpoint | Limit | Notes |
|---|---|---|
| POST /sign | 10 / min | Asynchronous and CPU-bound — about 1.5–2× the file's duration (up to ~10 min for 5 min) |
| POST /verify | 60 / min | Synchronous — signed content: about 5–10 s; unmarked: up to 15 min (900 s budget) |
Limits are applied per API key. Exceeding the limit returns HTTP 429.
All API requests require a Bearer token in the Authorization header. API keys start with krnl_ and are issued per-organization. Plaintext keys are shown only once at creation time — store them securely.
Authorization: Bearer krnl_<your-api-key>
| Scope | Grants access to |
|---|---|
| sign | POST /sign — submit media for watermark signing |
| verify | POST /verify — submit media for watermark verification |
| HTTP Status | Meaning |
|---|---|
| 401 | Missing or invalid API key |
| 403 | Key does not have the required scope, or author_id belongs to a different org |
| 429 | Rate limit exceeded — retry after the Retry-After header interval |
/signSubmit a media file for cryptographic watermark signing. The job is enqueued asynchronously; poll the status endpoint to retrieve the signed file URL. Requires the sign scope.
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
| file | File | The raw media file to sign (MP4, MOV, MKV, WebM, MP3, WAV, FLAC, OGG) |
| certificate_json | string (JSON) | JSON object describing the signing certificate (see schema below) |
{
"author_id": "<identity-uuid>",
"title": "optional media title",
"timestamp": "2026-05-04T12:00:00Z"
}HTTP 202 Accepted
{
"job_id": "arq:sign:<uuid>"
}The sign job runs asynchronously. Poll the status endpoint until status is complete or failed.
/sign/status/{job_id}{
"status": "complete",
"video_url": "https://transfer.kernelsecurity.tech/kernel-media/...",
"content_id": "<uuid>"
}curl -X POST https://transfer.kernelsecurity.tech/sign \ -H "Authorization: Bearer krnl_<key>" \ -F "[email protected]" \ -F 'certificate_json={"author_id":"<uuid>"}'
/verifySubmit a media file to check whether it carries a valid Kernel watermark. Returns HTTP 200 for all outcomes — a RED verdict is a valid result, not an error. Requires the verify scope.
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
| file | File | The media file to verify (same formats as /sign) |
HTTP 200 OK
{
"verdict": "VERIFIED" | "ATTESTED_AUDIO" | "ATTESTED_VIDEO" | "RED" | "NOT_DETECTED",
"content_id": "<uuid> | null",
"author_id": "<uuid> | null",
"author_name": "string | null",
"org_name": "string | null",
"red_reason": "string | null",
"wid_match": true | false | null,
"signature_valid": true | false | null,
"n_segments_total": 42,
"n_segments_decoded": 40,
"n_erasures": 2,
"fingerprint_confidence": 0.97,
"audio_verdict": "VERIFIED" | "RED" | null,
"video_verdict": "VERIFIED" | "RED" | null
}| Verdict | Meaning |
|---|---|
| VERIFIED | Both channels carry a valid Kernel signature: who signed the content is proven |
| ATTESTED_AUDIO | The audio carries a valid signature; the video could not be proven |
| ATTESTED_VIDEO | The video carries a valid signature; the audio could not be proven |
| RED | A Kernel mark was found but it does not prove the signature (see red_reason) |
| NOT_DETECTED | No registered content matches this file |
curl -X POST https://transfer.kernelsecurity.tech/verify \ -H "Authorization: Bearer krnl_<key>" \ -F "[email protected]"
API keys are managed by organization admins via the Admin → API Keys panel or these REST endpoints. All four endpoints require admin-level JWT authentication — they cannot be called with an API key.
/organizations/{org_id}/api-keysList all API keys for the organization (plaintext_key is always null in list responses).
| Parameter | Default | Description |
|---|---|---|
| page | 1 | Page number (1-indexed) |
| page_size | 20 | Results per page (max 100) |
HTTP 200 OK
{
"items": [
{
"key_id": "<uuid>",
"key_prefix": "krnl_ab12",
"name": "Production Key",
"plaintext_key": null,
"created_at": "2026-05-01T00:00:00Z",
"last_used_at": "2026-05-04T08:30:00Z",
"is_active": true,
"scopes": ["sign", "verify"],
"expires_at": null
}
],
"total": 3,
"page": 1,
"total_pages": 1
}/organizations/{org_id}/api-keysCreate a new API key. All fields are optional. The plaintext key is returned only in this response.
{
"name": "My Key",
"scopes": ["sign", "verify"],
"expires_at": "2027-01-01T00:00:00Z"
}⚠ Save the plaintext_key immediately — it will not be shown again.
HTTP 201 Created
{
"key_id": "<uuid>",
"key_prefix": "krnl_ab12",
"plaintext_key": "krnl_ab12cd34ef56...",
"scopes": ["sign", "verify"],
"expires_at": "2027-01-01T00:00:00Z",
"is_active": true
}/organizations/{org_id}/api-keys/{key_id}Rename a key (pass name: null to clear the name).
{ "name": "Renamed Key" }/organizations/{org_id}/api-keys/{key_id}Permanently revoke a key. The key will be deactivated and cannot be re-activated.
HTTP 204 No Content