Image authentication API: integration guide for developers
A technical guide to integrating Reality AI's image authentication API — covering endpoints, request/response formats, webhooks, error handling, and common integration patterns.
Integrating an image authentication API lets you run automated AI detection on every image that enters your system — at the moment of upload, during claims intake, in content moderation queues, or as part of KYC verification workflows. This guide covers Reality AI's image authentication API from a developer's perspective: architecture, authentication, endpoints, request and response formats, webhook integration, error handling, rate limits, and common integration patterns.
For product context on what the detection system does and why multi-model detection matters, see our platform overview.
API architecture overview
Reality AI's image authentication API is a REST API that accepts image files or URLs and returns structured detection results. The architecture is designed for production workloads:
- Stateless requests: Each API call is independent. No session management required.
- Synchronous and asynchronous modes: Single-image analysis is synchronous (response in < 2 seconds). Batch analysis and large files use an asynchronous model with webhook callbacks.
- Multi-model ensemble: Each request runs six detection models in parallel. Results are combined into a composite score with individual model outputs available for inspection.
- Regional endpoints: US (us-east-1), EU (eu-west-1), and APAC (ap-southeast-1) to support data residency requirements.
- Idempotent submission: Requests with the same image hash return cached results within a configurable TTL, preventing duplicate processing charges.
The base URL for the US region is:
```
https://api.checkreality.ai/v1
```
Authentication
All API requests require an API key passed in the Authorization header:
```
Authorization: Bearer YOUR_API_KEY
```
API keys are scoped to your organization and can be restricted to specific endpoints or IP ranges in the dashboard. Use separate keys for development, staging, and production environments.
Keys are rotated via the dashboard. We recommend rotating production keys every 90 days. Revoked keys return `401 Unauthorized` immediately.
Never embed API keys in client-side code. All calls to the image authentication API should originate from your backend.
Endpoints
### Single image analysis
POST /v1/analyze
Analyzes a single image synchronously. Returns results in the response body.
Request:
```json
{
"image_url": "https://your-storage.example.com/claims/photo-1234.jpg",
"options": {
"models": ["all"],
"metadata_analysis": true,
"return_heatmap": false,
"webhook_url": null
},
"reference_id": "claim-78234-photo-1"
}
```
Parameters:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `image_url` | string | Yes* | Publicly accessible URL of the image |
| `image_base64` | string | Yes* | Base64-encoded image (alternative to `image_url`) |
| `options.models` | array | No | Models to run. `["all"]` runs full ensemble. Options: `["gan", "diffusion", "noise", "metadata", "frequency", "splicing"]` |
| `options.metadata_analysis` | boolean | No | Include EXIF and provenance analysis. Default: `true` |
| `options.return_heatmap` | boolean | No | Include a pixel-level manipulation heatmap in response. Default: `false` |
| `options.webhook_url` | string | No | If provided, response is sent to webhook and endpoint returns `202 Accepted` immediately |
| `reference_id` | string | No | Your internal identifier for this request. Returned in response for correlation. |
*Either `image_url` or `image_base64` is required, not both.
Response (200 OK):
```json
{
"request_id": "req_9f3a2b1c4d5e6f",
"reference_id": "claim-78234-photo-1",
"status": "complete",
"processed_at": "2026-03-16T14:23:11Z",
"verdict": {
"label": "AI_GENERATED",
"confidence": 0.94,
"risk_level": "HIGH"
},
"model_results": {
"gan_detection": {
"score": 0.91,
"label": "SYNTHETIC"
},
"diffusion_detection": {
"score": 0.97,
"label": "SYNTHETIC"
},
"noise_analysis": {
"score": 0.89,
"label": "SYNTHETIC",
"detail": "No camera sensor noise pattern detected"
},
"metadata_analysis": {
"score": 0.95,
"label": "SUSPICIOUS",
"detail": "No EXIF data present. File creation timestamp inconsistent with claimed incident date.",
"exif_present": false,
"gps_present": false,
"device_fingerprint": null
},
"frequency_analysis": {
"score": 0.88,
"label": "SYNTHETIC",
"detail": "Periodic frequency artifacts detected at 64px intervals"
},
"splicing_detection": {
"score": 0.23,
"label": "AUTHENTIC",
"detail": "No localized manipulation regions detected"
}
},
"image_info": {
"width": 3024,
"height": 4032,
"format": "JPEG",
"file_size_bytes": 4821033,
"sha256": "a1b2c3d4e5f6..."
},
"processing_time_ms": 847
}
```
Verdict labels: `AUTHENTIC`, `AI_GENERATED`, `MANIPULATED`, `INCONCLUSIVE`
Risk levels: `LOW` (confidence < 0.6), `MEDIUM` (0.6–0.85), `HIGH` (> 0.85)
### Batch analysis
POST /v1/analyze/batch
Submits multiple images for asynchronous processing. Required for more than 5 images in a single request.
Request:
```json
{
"images": [
{
"image_url": "https://storage.example.com/claim-1/photo-a.jpg",
"reference_id": "claim-1-photo-a"
},
{
"image_url": "https://storage.example.com/claim-1/photo-b.jpg",
"reference_id": "claim-1-photo-b"
}
],
"options": {
"models": ["all"],
"metadata_analysis": true
},
"webhook_url": "https://your-backend.example.com/webhooks/checkreal",
"batch_reference_id": "claims-batch-2026-03-16-001"
}
```
Response (202 Accepted):
```json
{
"batch_id": "batch_7a8b9c0d1e2f",
"batch_reference_id": "claims-batch-2026-03-16-001",
"image_count": 2,
"estimated_completion_seconds": 12,
"status_url": "https://api.checkreality.ai/v1/batches/batch_7a8b9c0d1e2f"
}
```
### Batch status
GET /v1/batches/{batch_id}
Poll for batch completion status. Returns individual results as they complete.
Response:
```json
{
"batch_id": "batch_7a8b9c0d1e2f",
"status": "PROCESSING",
"total": 2,
"completed": 1,
"failed": 0,
"results": [
{
"reference_id": "claim-1-photo-a",
"status": "complete",
"verdict": {
"label": "AUTHENTIC",
"confidence": 0.91,
"risk_level": "LOW"
}
}
]
}
```
Webhook integration
For batch processing and high-volume workflows, webhooks are more efficient than polling. When a `webhook_url` is provided, the API sends a POST request to your endpoint when analysis completes.
Webhook payload (single image completion):
```json
{
"event": "analysis.complete",
"request_id": "req_9f3a2b1c4d5e6f",
"reference_id": "claim-78234-photo-1",
"verdict": {
"label": "AI_GENERATED",
"confidence": 0.94,
"risk_level": "HIGH"
},
"webhook_delivered_at": "2026-03-16T14:23:13Z"
}
```
Webhook payload (batch completion):
```json
{
"event": "batch.complete",
"batch_id": "batch_7a8b9c0d1e2f",
"batch_reference_id": "claims-batch-2026-03-16-001",
"total": 2,
"completed": 2,
"failed": 0,
"summary": {
"AUTHENTIC": 1,
"AI_GENERATED": 1,
"MANIPULATED": 0,
"INCONCLUSIVE": 0
}
}
```
Webhook security: All webhook requests include an `X-CheckReal-Signature` header containing an HMAC-SHA256 signature of the request body using your webhook secret. Verify this signature before processing webhook payloads:
```javascript
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
```
Webhook retry policy: Failed webhook deliveries (non-2xx response or timeout) are retried with exponential backoff: 5 seconds, 30 seconds, 2 minutes, 10 minutes, 1 hour. After 5 failed attempts, the delivery is abandoned and logged in the dashboard.
Your webhook endpoint must respond with a 2xx status within 10 seconds. For time-consuming processing, respond immediately and process the payload asynchronously.
Error handling
The API uses standard HTTP status codes:
| Code | Meaning | Action |
|------|---------|--------|
| 200 | Success | Process response |
| 202 | Accepted (async) | Wait for webhook or poll status |
| 400 | Bad request | Check request format and parameters |
| 401 | Unauthorized | Verify API key |
| 413 | Payload too large | Compress image or use URL instead of base64 |
| 422 | Unprocessable | Image format not supported or image too small |
| 429 | Rate limited | Back off and retry with Retry-After header |
| 500 | Server error | Retry with exponential backoff |
Error response body:
```json
{
"error": {
"code": "IMAGE_TOO_SMALL",
"message": "Image dimensions must be at least 100x100 pixels",
"request_id": "req_9f3a2b1c4d5e6f"
}
}
```
Common error codes: `INVALID_API_KEY`, `IMAGE_TOO_SMALL`, `UNSUPPORTED_FORMAT`, `URL_UNREACHABLE`, `FILE_SIZE_EXCEEDED`, `RATE_LIMIT_EXCEEDED`, `QUOTA_EXCEEDED`
Implement retry logic with exponential backoff for 429 and 5xx responses. Do not retry 4xx errors (except 429) without fixing the underlying request issue.
Rate limits
Default rate limits by plan:
| Plan | Requests/minute | Requests/day | Batch size (max images) |
|------|----------------|--------------|------------------------|
| Starter | 60 | 10,000 | 20 |
| Growth | 300 | 100,000 | 100 |
| Enterprise | Custom | Custom | 1,000 |
Rate limit headers are included in every response:
```
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 247
X-RateLimit-Reset: 1710598800
```
When you exceed rate limits, the API returns `429 Too Many Requests` with a `Retry-After` header specifying the number of seconds to wait.
For high-volume integrations, use batch endpoints to reduce request overhead and increase throughput within rate limits.
Supported formats and limits
Image formats: JPEG, PNG, WebP, HEIC, BMP, TIFF
Maximum file size: 20 MB (base64 or URL). For larger files, contact support.
Minimum dimensions: 100x100 pixels. Detection accuracy improves significantly at 500x500+.
URL requirements: Image URLs must be publicly accessible without authentication. For private storage, generate a signed URL with sufficient TTL (at least 60 seconds).
SDK options
Official SDKs are available for:
- Node.js: `npm install @checkreality/sdk`
- Python: `pip install checkreality-sdk`
- Go: `go get github.com/checkreality/go-sdk`
Example (Node.js):
```javascript
import { CheckRealClient } from '@checkreality/sdk';
const client = new CheckRealClient({ apiKey: process.env.CHECKREAL_API_KEY });
const result = await client.analyze({
imageUrl: 'https://storage.example.com/photo.jpg',
referenceId: 'my-reference-123',
});
console.log(result.verdict.label); // 'AUTHENTIC' | 'AI_GENERATED' | 'MANIPULATED'
console.log(result.verdict.confidence); // 0.0 – 1.0
console.log(result.verdict.riskLevel); // 'LOW' | 'MEDIUM' | 'HIGH'
```
For the full SDK reference, see our developer docs.
Common integration patterns
### Pattern 1: Insurance claims intake
In an insurance claims intake flow, photos are screened at upload before they reach an adjuster:
- Claimant uploads photos through FNOL portal
- Your backend receives the upload and stores the file
- Backend calls `POST /v1/analyze` for each photo
- High-risk results trigger SIU escalation flag in your claims management system
- Medium-risk results surface a review warning in the adjuster UI
- Low-risk results proceed normally
Key configuration: Use `reference_id` to match detection results back to specific claims and photos. Log `request_id` for audit trail purposes. Store detection results in your claims database with the SHA256 hash of the analyzed image.
### Pattern 2: User upload content moderation
For platforms that accept user-generated content, integrate detection into the upload processing pipeline:
- User uploads image
- Upload handler stores file and queues processing job
- Processing job submits image to `POST /v1/analyze/batch` (collect multiple uploads before batching)
- Webhook delivers results when analysis completes
- Results are written to your content database
- Content above risk threshold is held for moderation review or auto-rejected per your policy
Use webhooks rather than synchronous calls for user upload flows to avoid blocking upload completion on detection latency.
### Pattern 3: KYC verification
Identity verification flows can include AI detection as part of document and selfie review:
- User submits ID document photos and selfie
- Backend calls `POST /v1/analyze` for each image with `models: ["gan", "diffusion", "splicing"]`
- Synthetic face detection results are combined with liveness check results
- High-confidence AI generation in selfie triggers step-up verification or rejection
- Results are logged in the verification audit record
Metadata analysis is particularly valuable for ID documents — authentic document photos have EXIF data consistent with a mobile device capture, while fraudulent submissions often lack metadata or have inconsistent metadata.
For more context on integration patterns by use case, see our post on AI detection integration for enterprise teams.
Book a demo to get API credentials and walk through integration with your specific workflow.
Ready to verify what's real?
See how Reality AI authenticates images and documents for enterprise teams.
Book a demo