API Reference¶
Complete REST API documentation for Certana Backend.
Base URL¶
http://localhost:8000/v1
All endpoints are versioned with /v1 prefix.
Authentication¶
Bearer Token¶
Authorization: Bearer <jwt_token>
API Key¶
X-API-Key: <api_key>
OAuth2¶
Authorization: Bearer <oauth_token>
Response Format¶
All responses are JSON:
{
"data": {},
"message": "Success message",
"timestamp": "2024-01-15T10:30:00Z",
"request_id": "req_xxx"
}
Errors:
{
"detail": "Error message",
"error_code": "ERROR_CODE",
"timestamp": "2024-01-15T10:30:00Z"
}
Authentication Endpoints¶
Register User¶
POST /auth/register
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePassword123!",
"full_name": "John Doe"
}
Response (201 Created):
{
"id": "uuid",
"email": "user@example.com",
"full_name": "John Doe",
"tier": "free",
"created_at": "2024-01-15T10:30:00Z"
}
Login¶
POST /auth/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "SecurePassword123!"
}
Response (200 OK):
{
"access_token": "eyJhbGc...",
"refresh_token": "eyJhbGc...",
"token_type": "bearer",
"expires_in": 3600
}
Refresh Token¶
POST /auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJhbGc..."
}
Response (200 OK):
{
"access_token": "eyJhbGc...",
"token_type": "bearer",
"expires_in": 3600
}
Logout¶
POST /auth/logout
Authorization: Bearer <token>
Response (204 No Content)
Assets Endpoints¶
Upload Asset¶
POST /assets/
Authorization: Bearer <token>
Content-Type: multipart/form-data
file=<binary>
title=My Image
description=Image description
tags=tag1,tag2
track_a_enabled=true
track_b_enabled=true
track_c_enabled=true
metadata_tracking_enabled=true
blockchain_commit=true
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| file | binary | Yes | Image file (JPEG, PNG, TIFF, WebP) |
| title | string | No | Asset title |
| description | string | No | Asset description |
| tags | string | No | Comma-separated tags |
| track_a_enabled | boolean | No | Enable watermark track A |
| track_b_enabled | boolean | No | Enable watermark track B |
| track_c_enabled | boolean | No | Enable watermark track C (neural) |
| metadata_tracking_enabled | boolean | No | Extract and track metadata |
| blockchain_commit | boolean | No | Create blockchain commitment |
Response (201 Created):
{
"id": "uuid",
"organization_id": "uuid",
"cid": "bafyrei...",
"content_hash": "sha256hash",
"title": "My Image",
"mime_type": "image/jpeg",
"file_size_bytes": 102400,
"width": 1920,
"height": 1080,
"ipfs_cid": "bafyrei...",
"watermarked_cid": "bafyrei...",
"processing_status": "completed",
"created_at": "2024-01-15T10:30:00Z"
}
List Assets¶
GET /assets/?page=1&page_size=20&order=created_at&sort=desc
Authorization: Bearer <token>
Query Parameters:
| Name | Type | Default | Description |
|---|---|---|---|
| page | integer | 1 | Page number |
| page_size | integer | 20 | Items per page |
| order | string | created_at | Sort field |
| sort | string | desc | Sort direction (asc/desc) |
| tags | string | - | Filter by tags |
| status | string | - | Filter by processing_status |
Response (200 OK):
{
"items": [
{ "id": "uuid", ... }
],
"total": 42,
"page": 1,
"page_size": 20,
"pages": 3
}
Get Asset Details¶
GET /assets/{asset_id}
Authorization: Bearer <token>
Response (200 OK):
{
"id": "uuid",
"organization_id": "uuid",
"cid": "bafyrei...",
"content_hash": "sha256hash",
"title": "My Image",
"mime_type": "image/jpeg",
"file_size_bytes": 102400,
"width": 1920,
"height": 1080,
"ipfs_cid": "bafyrei...",
"watermarked_cid": "bafyrei...",
"processing_status": "completed",
"created_at": "2024-01-15T10:30:00Z"
}
Update Asset¶
PATCH /assets/{asset_id}
Authorization: Bearer <token>
Content-Type: application/json
{
"title": "Updated Title",
"description": "New description",
"tags": ["new", "tags"]
}
Response (200 OK):
{ ... updated asset ... }
Delete Asset¶
DELETE /assets/{asset_id}
Authorization: Bearer <token>
Response (204 No Content)
Verification Endpoints¶
Verify Image¶
POST /verify/
Content-Type: multipart/form-data
file=<binary>
include_tamper_map=true
Parameters:
| Name | Type | Required | Description |
|---|---|---|---|
| file | binary | Yes | Image to verify |
| include_tamper_map | boolean | No | Include pixel-level tamper visualization |
Authentication: Optional (Bearer token or API key)
Response (200 OK):
{
"is_authentic": true,
"confidence": 0.95,
"watermark": {
"track_a_detected": true,
"track_b_detected": true,
"track_c_detected": true,
"payload": "base64encoded"
},
"fingerprint": {
"similarity_score": 0.89,
"match_count": 15,
"top_matches": [
{
"asset_id": "uuid",
"similarity": 0.95,
"distance": 0.05
}
]
},
"blockchain": {
"commitment_found": true,
"tx_hash": "Ax5q...",
"signature_valid": true,
"on_chain": true
},
"metadata": {
"exif_intact": true,
"modifications": []
},
"tamper_map": "base64image",
"verdict": "authentic",
"details": "Image is authentic with high confidence"
}
Batch Verification¶
POST /verify/batch
Content-Type: multipart/form-data
files=<binary1>&files=<binary2>&files=<binary3>
include_tamper_map=false
Response (200 OK):
{
"results": [
{ ... verification result ... },
{ ... verification result ... }
],
"total": 3,
"successful": 3,
"failed": 0,
"processing_time_ms": 5432
}
Get Verification History¶
GET /verify/history?page=1&page_size=20&verdict=authentic
Authorization: Bearer <token>
Query Parameters:
| Name | Type | Description |
|---|---|---|
| page | integer | Page number |
| page_size | integer | Items per page |
| verdict | string | Filter by verdict (authentic/forged/unknown) |
| start_date | string | ISO 8601 start date |
| end_date | string | ISO 8601 end date |
Response (200 OK):
{
"items": [
{
"id": "uuid",
"verified_at": "2024-01-15T10:30:00Z",
"verdict": "authentic",
"confidence": 0.95,
"asset_id": "uuid",
"matched_asset": { ... }
}
],
"total": 42,
"page": 1
}
Organization Endpoints¶
Create Organization¶
POST /organizations/
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Acme Corp",
"slug": "acme-corp",
"plan": "pro"
}
Response (201 Created):
{
"id": "uuid",
"name": "Acme Corp",
"slug": "acme-corp",
"owner_id": "uuid",
"plan": "pro",
"created_at": "2024-01-15T10:30:00Z"
}
List Organizations¶
GET /organizations/
Authorization: Bearer <token>
Response (200 OK):
{
"items": [ { ... } ],
"total": 5
}
Get Organization Details¶
GET /organizations/{org_id}
Authorization: Bearer <token>
Response (200 OK):
{
"id": "uuid",
"name": "Acme Corp",
"plan": "pro",
"members_count": 8,
"assets_count": 125,
"created_at": "2024-01-15T10:30:00Z"
}
API Keys Endpoints¶
Create API Key¶
POST /api-keys/
Authorization: Bearer <token>
Content-Type: application/json
{
"name": "Production API Key",
"scopes": ["read", "verify"],
"expires_in_days": 90
}
Response (201 Created):
{
"id": "uuid",
"key": "cert_pk_...",
"name": "Production API Key",
"scopes": ["read", "verify"],
"expires_at": "2024-04-15T10:30:00Z",
"created_at": "2024-01-15T10:30:00Z",
"last_used_at": null
}
List API Keys¶
GET /api-keys/
Authorization: Bearer <token>
Response (200 OK):
{
"items": [
{
"id": "uuid",
"key": "cert_pk_...",
"name": "Production API Key",
"scopes": ["read", "verify"],
"expires_at": "2024-04-15T10:30:00Z",
"last_used_at": "2024-01-14T15:22:00Z",
"is_active": true
}
],
"total": 3
}
Validate API Key¶
POST /api-keys/validate
X-API-Key: <api_key>
Response (200 OK):
{
"valid": true,
"scopes": ["read", "verify"],
"key_id": "uuid",
"name": "Production API Key",
"is_active": true,
"expires_at": "2024-04-15T10:30:00Z",
"rate_limit": {
"per_hour": 5000,
"per_day": 50000
}
}
Revoke API Key¶
DELETE /api-keys/{key_id}
Authorization: Bearer <token>
Response (204 No Content)
Blockchain Endpoints¶
Create Commitment¶
POST /blockchain/commit
Authorization: Bearer <token>
Content-Type: application/json
{
"asset_id": "uuid",
"watermark_hash": "sha256hash",
"metadata": { ... }
}
Response (201 Created):
{
"commitment_id": "uuid",
"tx_hash": "Ax5q7n...",
"signature": "base64sig",
"commitment_hash": "sha256hash",
"on_chain_at": "2024-01-15T10:30:05Z",
"confirmation_status": "finalized"
}
Get Commitment Details¶
GET /blockchain/commitment/{commitment_id}
Response (200 OK):
{
"commitment_id": "uuid",
"asset_id": "uuid",
"tx_hash": "Ax5q7n...",
"commitment_hash": "sha256hash",
"on_chain_at": "2024-01-15T10:30:05Z",
"confirmation_status": "finalized",
"verified": true
}
Error Codes¶
| Code | HTTP | Description |
|---|---|---|
| INVALID_CREDENTIALS | 401 | Invalid email or password |
| TOKEN_EXPIRED | 401 | JWT token has expired |
| INVALID_API_KEY | 401 | API key is invalid or revoked |
| QUOTA_EXCEEDED | 403 | Usage quota exceeded |
| ASSET_NOT_FOUND | 404 | Asset does not exist |
| FILE_TOO_LARGE | 400 | File exceeds size limit |
| INVALID_FILE_TYPE | 400 | Unsupported file type |
| PROCESSING_FAILED | 500 | Asset processing error |
| BLOCKCHAIN_ERROR | 500 | Blockchain operation failed |
| RATE_LIMITED | 429 | Too many requests |
Rate Limits¶
- Free tier: 10 verifications/day, 100 uploads/month
- Pro tier: 1000 verifications/day, 10000 uploads/month
- Enterprise: Custom limits
Rate limit headers:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1705334400
Pagination¶
All list endpoints support pagination:
?page=1&page_size=20
Response includes:
{
"items": [...],
"total": 100,
"page": 1,
"page_size": 20,
"pages": 5
}
Webhooks¶
Create webhooks to receive events:
POST /webhooks/
Authorization: Bearer <token>
Content-Type: application/json
{
"url": "https://your-domain.com/webhook",
"events": ["asset.processed", "verification.completed"],
"active": true
}
Webhook Payload:
{
"event": "asset.processed",
"timestamp": "2024-01-15T10:30:00Z",
"data": {
"asset_id": "uuid",
"status": "completed"
}
}
Pagination Examples¶
Get second page of assets¶
curl "http://localhost:8000/v1/assets/?page=2&page_size=50" \
-H "Authorization: Bearer <token>"
Search with pagination¶
curl "http://localhost:8000/v1/assets/search/?q=logo&page=1&page_size=10" \
-H "Authorization: Bearer <token>"