Content Authenticity Initiative
Official Member
C2PA Real Implementation
โœ“ Using official c2pa-python library โ€ข Official CAI member

API Documentation

Enterprise-grade AI compliance automation for EU AI Act and China Cybersecurity Law requirements.

Quick Start

Get started with AIGC Compliance API in under 5 minutes:

  1. Get your API key from the dashboard
  2. Make your first request to /comply
  3. Download your compliance-ready image

Authentication

All API requests require authentication via Bearer token in the Authorization header:

Authorization: Bearer your-api-key

Security Note: Never expose your API key in client-side code. Use server-side proxy endpoints for browser applications.

๐Ÿ“‹ Professional Response Format

All API responses follow a consistent professional format with success, message, and structured data fields. This ensures immediate status checking and clear error handling across all endpoints.

๐Ÿ” OAuth Authentication (Google & GitHub)

AIGC Compliance API supports OAuth 2.0 authentication for user login and signup, allowing seamless integration with Google and GitHub accounts.

โš ๏ธ Important: Terms & Conditions Requirement

All OAuth requests MUST include accept_terms: true in the request body. Users must accept Terms of Service and Privacy Policy before authentication. Requests without this field or with accept_terms: false will be rejected with HTTP 400.

Supported Providers

  • Google OAuth 2.0 - Sign in with Google account
  • GitHub OAuth - Sign in with GitHub account

OAuth Flow Overview

  1. User clicks "Sign in with Google/GitHub" on your frontend
  2. Frontend displays Terms & Conditions checkbox (REQUIRED)
  3. User accepts terms by checking the checkbox
  4. Frontend calls GET /auth/oauth/{provider}/authorize to get authorization URL
  5. User is redirected to Google/GitHub authorization page
  6. After authorization, provider redirects to your callback URL with code and state
  7. Frontend calls POST /auth/oauth/{provider} with code, state, and accept_terms: true
  8. Backend validates terms acceptance, exchanges code for user info, creates/updates user account
  9. API returns user data and API key

GET /auth/oauth/{provider}/authorize

Generate OAuth authorization URL. Replace {provider} with google or github.

Example Request

curl -X GET \
  https://aigc-compliance-api-production.up.railway.app/auth/oauth/google/authorize

Example Response

{
  "authorization_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&state=...",
  "provider": "google"
}

POST /auth/oauth/google

Complete Google OAuth authentication. Automatically creates new user account or logs in existing user.

Request Body (JSON)

  • code - Authorization code from Google callback โ€” required
  • state - State parameter from callback (CSRF protection) โ€” required
  • redirect_uri - Your registered callback URL (must be HTTPS) โ€” required
  • accept_terms - MUST be true โ€” required

Example Request

curl -X POST \
  https://aigc-compliance-api-production.up.railway.app/auth/oauth/google \
  -H "Content-Type: application/json" \
  -d '{
    "code": "4/0AeanS0a...",
    "state": "eyJwcm92aWRlciI6Imdvb2dsZSIsInRpbWVzdGFtcCI6...",
    "redirect_uri": "https://yourdomain.com/oauth-callback",
    "accept_terms": true
  }'

Success Response (200 OK)

{
  "success": true,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@gmail.com",
    "name": "John Doe",
    "provider": "google",
    "avatar": "https://lh3.googleusercontent.com/..."
  },
  "api_key": "sk-abc123xyz789...",
  "message": "Google OAuth authentication successful"
}

Error Response: Terms Not Accepted (400)

{
  "success": false,
  "error": "HTTP_400",
  "message": "You must accept the terms and conditions to continue",
  "details": {
    "status_code": 400,
    "path": "/auth/oauth/google"
  },
  "timestamp": "2025-10-05T20:30:37.091398"
}

โŒ Common Errors

  • accept_terms: false โ†’ 400 "You must accept the terms..."
  • Missing accept_terms field โ†’ 400 "You must accept the terms..."
  • Invalid or expired state โ†’ 400 "Invalid state parameter"
  • Invalid code โ†’ 400 "Google token exchange failed"

POST /auth/oauth/github

Complete GitHub OAuth authentication. Same requirements as Google OAuth.

Request Body (JSON)

Same structure as Google OAuth:

  • code - Authorization code from GitHub โ€” required
  • state - State parameter (CSRF protection) โ€” required
  • redirect_uri - Your callback URL (HTTPS) โ€” required
  • accept_terms - MUST be true โ€” required

Example Request

curl -X POST \
  https://aigc-compliance-api-production.up.railway.app/auth/oauth/github \
  -H "Content-Type: application/json" \
  -d '{
    "code": "a1b2c3d4e5f6",
    "state": "eyJwcm92aWRlciI6ImdpdGh1YiIsInRpbWVzdGFtcCI6...",
    "redirect_uri": "https://yourdomain.com/oauth-callback",
    "accept_terms": true
  }'

Response format identical to Google OAuth.

๐Ÿ“ Frontend Implementation Example

1. HTML: Terms & Conditions Checkbox (REQUIRED)

<!-- STEP 1: Add Terms Checkbox BEFORE OAuth Buttons -->
<div class="terms-container">
    <label>
        <input type="checkbox" id="oauth-terms-checkbox" required>
        I accept the 
        <a href="/terms" target="_blank">Terms of Service</a> 
        and 
        <a href="/privacy" target="_blank">Privacy Policy</a>
    </label>
</div>

<!-- STEP 2: OAuth Buttons (disabled by default) -->
<button id="google-oauth-btn" onclick="loginWithGoogle()" disabled>
    Sign in with Google
</button>
<button id="github-oauth-btn" onclick="loginWithGitHub()" disabled>
    Sign in with GitHub
</button>

2. JavaScript: Enable Buttons on Terms Acceptance

// Enable OAuth buttons when terms are accepted
const termsCheckbox = document.getElementById('oauth-terms-checkbox');
const googleBtn = document.getElementById('google-oauth-btn');
const githubBtn = document.getElementById('github-oauth-btn');

termsCheckbox.addEventListener('change', (e) => {
    googleBtn.disabled = !e.target.checked;
    githubBtn.disabled = !e.target.checked;
});

3. JavaScript: OAuth Initiation with Terms Validation

async function loginWithGoogle() {
    // Validate terms acceptance
    const termsAccepted = document.getElementById('oauth-terms-checkbox').checked;
    if (!termsAccepted) {
        alert('Please accept the Terms of Service to continue');
        return;
    }
    
    // Store terms acceptance for callback
    localStorage.setItem('oauth_terms_accepted', 'true');
    
    // Get authorization URL
    const response = await fetch(
        'https://aigc-compliance-api-production.up.railway.app/auth/oauth/google/authorize'
    );
    const data = await response.json();
    
    // Redirect to Google
    window.location.href = data.authorization_url;
}

4. JavaScript: Handle OAuth Callback

// In your oauth-callback.html page
const urlParams = new URLSearchParams(window.location.search);
const code = urlParams.get('code');
const state = urlParams.get('state');
const termsAccepted = localStorage.getItem('oauth_terms_accepted') === 'true';

if (!termsAccepted) {
    alert('Terms must be accepted');
    window.location.href = '/login.html';
    return;
}

// Complete OAuth authentication
const response = await fetch(
    'https://aigc-compliance-api-production.up.railway.app/auth/oauth/google',
    {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            code: code,
            state: state,
            redirect_uri: 'https://yourdomain.com/oauth-callback',
            accept_terms: true  // โ† CRITICAL: Must be true
        })
    }
);

const data = await response.json();

if (data.success) {
    // Store API key and user data
    localStorage.setItem('apiKey', data.api_key);
    localStorage.setItem('user', JSON.stringify(data.user));
    
    // Clear OAuth state
    localStorage.removeItem('oauth_terms_accepted');
    
    // Redirect to dashboard
    window.location.href = '/dashboard.html';
} else {
    alert('Authentication failed: ' + data.message);
}

Security Notes

  • โœ… CSRF Protection: State parameter validated server-side (10-minute expiry)
  • โœ… Terms Enforcement: 3-layer validation (UI + Frontend JS + Backend API)
  • โœ… HTTPS Required: All redirect URIs must use HTTPS
  • โœ… API Key Auto-Generation: New users receive API key automatically
  • โœ… Free Plan Default: OAuth users start with free plan (100 API calls)

Main Endpoint

POST /comply

Process an image file for compliance with EU AI Act or China Cybersecurity Law. Accepts multipart/form-data for direct file uploads.

Parameters

  • file - Image file (PNG, JPG, JPEG, max 10MB) โ€” required
  • region - "EU" or "CN" โ€” required
  • watermark_text - Custom watermark text (plan restrictions apply) โ€” optional
  • watermark_position - "bottom-right", "bottom-left", "top-right", "top-left" โ€” optional
  • logo_file - Logo file for watermark (PNG/JPEG, plan restrictions apply) โ€” optional
  • include_base64 - "true" or "false" โ€” optional (default: false)
  • save_to_disk - "true" or "false" โ€” optional (default: true)

Example Request (cURL)

curl -X POST \
  https://aigc-compliance-api-production.up.railway.app/comply \
  -H "Authorization: Bearer your-api-key" \
  -F "file=@ai-generated-image.jpg" \
  -F "region=EU" \
  -F "include_base64=true" \
  -F "metadata_level=detailed"

Response Schema (200 OK)

{
  "success": true,
  "message": "Image successfully processed for EU compliance",
  "status": "compliant",
  "processed_file_url": "https://aigc-compliance-api-production.up.railway.app/download/processed_eu_20250917_123456_a1b2c3d4.png",
  "metadata": {
    "region": "EU",
    "watermark_applied": true,
    "c2pa_signed": true,
    "processing_time_ms": 388,
    "file_size_bytes": 797024,
    "compliance_version": "1.0",
    "timestamp": "2025-10-04T22:15:30.123456",
    "processing_method": "c2pa_metadata_and_watermark",
    "region_specific_data": {
      "c2pa_info": {
        "c2pa_compliant": true,
        "c2pa_version": "1.3",
        "claim_signature": "sig_eu_123456789",
        "manifest_hash": "manifest_abc123def456",
        "provenance_data": {
          "creator": "AI Model XYZ",
          "creation_time": "2025-10-04T22:15:30Z",
          "ai_generated": true,
          "model_version": "v2.1"
        }
      },
      "eu_ai_act_article": "Article 52 - Transparency Obligations",
      "watermark_text": "AI Generated"
      },
      "processing_details": {
        "original_size": [1920, 1080],
        "processed_size": [1920, 1080],
        "original_format": "JPEG",
        "output_format": "PNG"
      }
    }
  },
  "base64_image": null  // included if include_base64=true
}

// Response Headers
X-RateLimit-Limit: 10000
X-RateLimit-Remaining: 9995
X-RateLimit-Reset: 2025-11-01T00:00:00Z

China Region Response Example

{
  "success": true,
  "message": "Image successfully processed for CN compliance",
  "status": "compliant",
  "processed_file_url": "https://aigc-compliance-api-production.up.railway.app/download/processed_cn_20251004_223015_xyz789.png",
  "metadata": {
    "region": "CN",
    "watermark_applied": true,
    "c2pa_signed": false,
    "processing_time_ms": 445,
    "file_size_bytes": 812340,
    "compliance_version": "1.0",
    "timestamp": "2025-10-04T22:30:15.456789",
    "processing_method": "watermark_and_metadata",
    "region_specific_data": {
      "cn_metadata": {
        "cybersecurity_law_compliance": {
          "data_localization_compliant": true,
          "content_review_status": "approved",
          "algorithm_registration": "ALG-CN-2025-001234"
        },
        "watermark_info": {
          "watermark_type": "visible_text",
          "watermark_text": "AIGC",
          "watermark_position": "bottom-right",
          "watermark_applied": true
        },
        "content_labeling": {
          "ai_generated_label": "ๆœฌๅ†…ๅฎน็”ฑไบบๅทฅๆ™บ่ƒฝ็”Ÿๆˆ",
          "label_visibility": "visible"
        }
      },
      "processing_details": {
        "original_size": [1920, 1080],
        "processed_size": [1920, 1080],
        "original_format": "PNG",
        "output_format": "PNG"
      }
    }
  },
  "base64_image": null
}

Error Responses

// 400 Bad Request
{
  "error": "INVALID_REGION",
  "message": "Supported regions: EU, CN",
  "details": {
    "status_code": 400,
    "provided_region": "US"
  }
}

// 413 Payload Too Large
{
  "error": "FILE_TOO_LARGE",
  "message": "Maximum file size is 10MB",
  "details": {
    "status_code": 413,
    "file_size_mb": 15.7,
    "max_size_mb": 10
  }
}

// 429 Rate Limit Exceeded
{
  "error": "RATE_LIMIT_EXCEEDED",
  "message": "Monthly quota exceeded",
  "details": {
    "status_code": 429,
    "quota_limit": 10000,
    "quota_used": 10000,
    "reset_date": "2025-10-01T00:00:00Z"
  }
}

๐ŸŽจ Watermark Customization

Professional watermark control with plan-based features. Customize text, position, opacity, and size to match your brand.

Available Parameters

watermark_text

  • Type: string (optional)
  • Description: Custom watermark text
  • Plan Restrictions:
    • Free: Fixed "AIGC" (no customization)
    • Starter: Up to 10 characters
    • Professional: Up to 20 characters
    • Enterprise: Up to 50 characters
  • Example: "Madrid 2024", "ยฉ MyCompany"

watermark_position

  • Type: string (optional, default: "bottom-right")
  • Options: bottom-right, bottom-left, top-right, top-left, center
  • Plan Restrictions:
    • Free/Starter: bottom-right only
    • Professional: bottom-right, bottom-left
    • Enterprise: All positions

watermark_opacity

  • Type: float (optional, range: 0.0-1.0)
  • Description: Watermark visibility (0.0 = invisible, 1.0 = fully opaque)
  • Plan Restrictions:
    • Free: Fixed 0.5 (50%)
    • Starter: 0.4-0.7 (40%-70%)
    • Professional: 0.3-0.8 (30%-80%)
    • Enterprise: 0.1-1.0 (10%-100%)
  • Example: 0.65 for 65% opacity

watermark_size

  • Type: float (optional, range: 0.5-2.0)
  • Description: Size multiplier (1.0 = default, 2.0 = double size)
  • Plan Restrictions:
    • Free: Fixed 1.0 (100%)
    • Starter: 0.8-1.5 (80%-150%)
    • Professional: 0.6-1.8 (60%-180%)
    • Enterprise: 0.5-2.0 (50%-200%)
  • Example: 1.5 for 150% size (50% larger)

logo_file

  • Type: file (optional, PNG/JPEG)
  • Description: Custom logo overlay on watermark
  • Plan Restrictions:
    • Free/Starter: Not available
    • Professional: Max 100KB
    • Enterprise: Max 200KB
  • Note: Logo scales with watermark_size parameter

Example: Full Customization (Enterprise)

curl -X POST "https://aigc-compliance-api-production.up.railway.app/comply" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@image.jpg" \
  -F "region=EU" \
  -F "watermark_text=ยฉ MyBrand 2024" \
  -F "watermark_position=center" \
  -F "watermark_opacity=0.75" \
  -F "watermark_size=1.5" \
  -F "logo_file=@logo.png" \
  -F "save_to_disk=true"

Plan Features Comparison

Feature Free Starter Professional Enterprise
Custom Text โŒ 10 chars 20 chars 50 chars
Positions 1 1 2 5 (all)
Opacity Control Fixed 50% 40-70% 30-80% 10-100%
Size Control Fixed 100% 80-150% 60-180% 50-200%
Logo Upload โŒ โŒ โœ… 100KB โœ… 200KB
API Calls 100 lifetime 10K/month 50K/month 500K/month

๐Ÿ’ก Best Practices

  • Opacity: Use 0.5-0.7 for subtle watermarks, 0.7-0.9 for prominent branding
  • Size: Default 1.0x works for most cases. Use 1.5x for small images or 0.7x for large images
  • Position: bottom-right is least intrusive, center is most visible
  • Logo + Text: Combine both for professional branding (Pro+ plans)
  • Testing: Use the Dashboard to preview settings before API integration

โšก Async Processing Endpoints

90% Faster Response Times - Professional & Enterprise Plans Only

Async endpoints return immediately (~250ms) while processing your image in the background. Perfect for high-volume production environments where speed matters.

POST /comply/async PROFESSIONAL+

Submit image for asynchronous processing - returns job_id immediately.

โš ๏ธ Plan Requirements:
  • Free Plan: โŒ Not available (use POST /comply instead)
  • Professional Plan: โœ… Standard queue processing
  • Enterprise Plan: โœ… Priority queue + guaranteed <500ms response

Headers

Authorization: Bearer your-api-key-here
Content-Type: multipart/form-data

Request Parameters (multipart/form-data)

Parameter Type Required Description
file File โœ… Yes Image file (PNG/JPG, max 10MB)
region String โœ… Yes EU or CN
webhook_url String โŒ Optional URL to receive completion notification
watermark_text String โŒ Optional Custom watermark text (plan limits apply)
watermark_position String โŒ Optional bottom-right, bottom-left, top-right, top-left, center
watermark_opacity Float โŒ Optional 0.0-1.0 (plan limits apply)
watermark_size Float โŒ Optional 0.5-2.0 (plan limits apply)

Example Request (cURL)

curl -X POST https://aigc-compliance-api-production.up.railway.app/comply/async \
  -H "Authorization: Bearer your-api-key-here" \
  -F "file=@image.jpg" \
  -F "region=EU" \
  -F "webhook_url=https://your-server.com/webhook"

Response (Success - 200) - Immediate Response in ~250ms

{
  "success": true,
  "message": "Job submitted for processing",
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "pending",
  "status_url": "/comply/async/f8c6101e-dee3-4303-9478-9ab388fc731b",
  "estimated_completion_time": "2-5 seconds",
  "webhook_url": "https://your-server.com/webhook",
  "processing_time_ms": 246.57
}

Response (Error - 403) - Free Plan User

{
  "error": "async_endpoint_not_available",
  "message": "Async processing requires Professional or Enterprise plan",
  "current_plan": "free",
  "upgrade_url": "https://aigc-compliance.com/payment.html",
  "alternative": "Use POST /comply for synchronous processing (included in Free plan)"
}

GET /comply/async/{job_id} PROFESSIONAL+

Check status and retrieve results of async processing job.

Headers

Authorization: Bearer your-api-key-here

URL Parameters

Parameter Type Description
job_id String (UUID) Job ID returned from POST /comply/async

Possible Job Statuses

  • pending - Job queued, waiting to start
  • processing - Job currently being processed
  • completed - Job finished successfully (includes result with processed image URL)
  • failed - Job failed (includes error message)

Example Request

curl -X GET https://aigc-compliance-api-production.up.railway.app/comply/async/f8c6101e-dee3-4303-9478-9ab388fc731b \
  -H "Authorization: Bearer your-api-key-here"

Response (Pending)

{
  "success": true,
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "pending",
  "created_at": "2025-10-26T13:19:42Z",
  "updated_at": "2025-10-26T13:19:42Z",
  "result": null,
  "error": null
}

Response (Completed)

{
  "success": true,
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "completed",
  "created_at": "2025-10-26T13:19:42Z",
  "updated_at": "2025-10-26T13:19:44Z",
  "result": {
    "processed_file_url": "https://res.cloudinary.com/dzl9v6xrx/image/upload/v1761484783/aigc-compliance/EU/processed_image.png",
    "metadata": {
      "original_size": [1024, 1024],
      "processing_method": "real_c2pa_metadata_and_watermark",
      "watermark_applied": true,
      "c2pa_compliant": true,
      "timestamp": "2025-10-26T13:19:44Z"
    },
    "file_hash": "2b3f8b509bb91879bd6728b876fe2dba68b6f897d8d6d48233697c56d91a9424"
  },
  "error": null
}

Response (Failed)

{
  "success": true,
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "failed",
  "created_at": "2025-10-26T13:19:42Z",
  "updated_at": "2025-10-26T13:19:43Z",
  "result": null,
  "error": "Invalid image format"
}

๐Ÿš€ Async vs Sync Performance Comparison

Metric Sync (POST /comply) Async (POST /comply/async)
Initial Response Time 2-6 seconds โŒ ~250ms โœ…
Total Processing Time 2-6 seconds 2-5 seconds (background)
Blocks API Call Yes No
Webhook Support No Yes
Best For Simple integrations Production, high-volume
Available Plans All plans Professional & Enterprise

๐Ÿ”” Webhook Notifications

When you provide a webhook_url, we'll send a POST request when processing completes:

Webhook Payload (Completed)

{
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "completed",
  "result": {
    "processed_file_url": "https://res.cloudinary.com/.../processed_image.png",
    "metadata": { ... },
    "file_hash": "2b3f8b..."
  }
}

Webhook Payload (Failed)

{
  "job_id": "f8c6101e-dee3-4303-9478-9ab388fc731b",
  "status": "failed",
  "error": "Invalid image format"
}

Requirements: Your webhook endpoint must respond with 2xx status within 5 seconds.

๐Ÿ“Š Migration Guide: Sync โ†’ Async

Before (Sync)

import requests

response = requests.post(
    "https://aigc-compliance-api-production.up.railway.app/comply",
    headers={"Authorization": "Bearer your-api-key"},
    files={"file": open("image.jpg", "rb")},
    data={"region": "EU"}
)
# Waits 2-6 seconds here โฐ
result = response.json()
processed_url = result["processed_file_url"]

After (Async)

import requests
import time

# Step 1: Submit job (returns immediately ~250ms) โšก
response = requests.post(
    "https://aigc-compliance-api-production.up.railway.app/comply/async",
    headers={"Authorization": "Bearer your-api-key"},
    files={"file": open("image.jpg", "rb")},
    data={"region": "EU", "webhook_url": "https://your-server.com/webhook"}
)
job_id = response.json()["job_id"]

# Step 2: Poll for status (or wait for webhook)
while True:
    status_response = requests.get(
        f"https://aigc-compliance-api-production.up.railway.app/comply/async/{job_id}",
        headers={"Authorization": "Bearer your-api-key"}
    )
    status_data = status_response.json()
    
    if status_data["status"] == "completed":
        processed_url = status_data["result"]["processed_file_url"]
        break
    elif status_data["status"] == "failed":
        raise Exception(status_data["error"])
    
    time.sleep(1)  # Poll every second

Best Practice: Use Webhooks

# Submit with webhook - no polling needed!
response = requests.post(
    "https://aigc-compliance-api-production.up.railway.app/comply/async",
    headers={"Authorization": "Bearer your-api-key"},
    files={"file": open("image.jpg", "rb")},
    data={
        "region": "EU",
        "webhook_url": "https://your-server.com/webhook"  # We notify you when done
    }
)
# Your server receives POST webhook when processing completes โœ…

Additional Endpoints

GET /health

Service health check and status information.

Example Request

curl -X GET https://aigc-compliance-api-production.up.railway.app/health

Response (Success - 200)

{
  "status": "healthy",
  "timestamp": "2025-09-19T10:30:00Z",
  "version": "1.0.0",
  "services": {
    "image_processor": "operational",
    "c2pa_handler": "operational",
    "metadata_injector": "operational",
    "redis": "connected"
  }
}

GET /download/{filename}

Download processed files by filename. No authentication required.

Example Request

curl -X GET https://aigc-compliance-api-production.up.railway.app/download/processed-image.jpg

POST /api/register/register

User registration endpoint to create new accounts and get API keys.

Request Body

{
  "email": "john@company.com",
  "password": "SecurePass123!",
  "first_name": "John",
  "last_name": "Doe",
  "company_name": "Your Company",
  "plan": "free"
}

Response (Success - 201)

{
  "success": true,
  "message": "User registered successfully",
  "user_id": "uuid-here",
  "api_key": "your-api-key-here"
}

POST /api/login

User login endpoint to authenticate and retrieve API key.

Request Body

{
  "email": "john@company.com",
  "password": "SecurePass123!"
}

Response (Success - 200)

{
  "success": true,
  "message": "Login successful",
  "api_key": "your-api-key-here",
  "user_id": "uuid-here"
}

GET /api/usage

Get usage statistics for the authenticated user. Requires API key authentication.

Example Request

curl -X GET https://aigc-compliance-api-production.up.railway.app/api/usage \
  -H "Authorization: Bearer your-api-key"

Response (Success - 200)

{
  "user_id": "uuid-here",
  "email": "john@company.com",
  "plan": "professional",
  "api_calls_used": 1250,
  "api_calls_limit": 50000,
  "remaining_calls": 48750,
  "usage_percentage": 2.5,
  "reset_date": "2025-11-01T00:00:00Z"
}

POST /api/cancel-subscription

Cancel active subscription. Requires API key authentication.

Request Body

{
  "reason": "No longer needed" // optional
}

Response (Success - 200)

{
  "success": true,
  "message": "Subscription cancelled successfully",
  "effective_date": "2025-11-01T00:00:00Z"
}

DELETE /api/user

Delete user account and all associated data. Requires API key authentication. This action is irreversible.

Example Request

curl -X DELETE https://aigc-compliance-api-production.up.railway.app/api/user \
  -H "Authorization: Bearer your-api-key"

Response (Success - 200)

{
  "success": true,
  "message": "User account deleted successfully",
  "deleted_user": {
    "user_id": "uuid-here",
    "email": "john@company.com"
  },
  "invalidated_keys": 1
}

POST /api/checkout/create-session

Create Stripe checkout session for subscription purchase.

Request Body

{
  "plan": "professional",
  "success_url": "https://yoursite.com/success",
  "cancel_url": "https://yoursite.com/cancel"
}

Response (Success - 200)

{
  "success": true,
  "checkout_url": "https://checkout.stripe.com/...",
  "session_id": "cs_test_...",
  "message": "Checkout session created"
}

Legacy Endpoint (URL-based)

POST /v1/tag

DEPRECATED Process an image via URL. Use /comply for new integrations.

Request Body

{
  "image_url": "https://example.com/ai-image.jpg",
  "compliance_regions": ["EU"]
}

Response (Success - 200)

{
  "status": "success",
  "region_applied": "EU",
  "file_hash": "a1b2c3d4e5f6...",
  "download_url": "https://aigc-compliance-api-production.up.railway.app/download/...",
  "processing_time_ms": 45
}

File Download

Use the download_url from the response to retrieve your compliance-ready image.

Download Example

# Download processed file
curl -O "https://aigc-compliance-api-production.up.railway.app/download/processed_eu_20250917_123456_a1b2c3d4.png"

# Or with custom filename
curl -o "my-compliant-image.png" \
  "https://aigc-compliance-api-production.up.railway.app/download/processed_eu_20250917_123456_a1b2c3d4.png"

Important: Download URLs expire after 7 days. Save files to your storage immediately after processing.

Watermark Customization

For CN region compliance, customize watermarks based on your subscription plan:

Plan Features

Feature Free Starter Professional Enterprise
Custom Text โŒ โœ… (10 chars) โœ… (20 chars) โœ… (50 chars)
Logo Upload โŒ โŒ โœ… (100KB) โœ… (200KB)
Position Control bottom-right only bottom-right only bottom-right, bottom-left All positions
Default Text "AIGC" "AIGC" "AIGC" "AIGC"

Professional Plan Example with Logo

curl -X POST "https://aigc-compliance-api-production.up.railway.app/comply" \
  -H "Authorization: Bearer your-api-key" \
  -F "file=@image.jpg" \
  -F "region=CN" \
  -F "watermark_text=Company Name" \
  -F "logo_file=@logo.png" \
  -F "watermark_position=bottom-left"

Security Validation

The API enforces strict watermark validation:

  • Forbidden patterns: transparent, invisible, hidden, script tags
  • Content filtering: Profanity and inappropriate content blocked
  • Plan enforcement: Features strictly limited by subscription tier

Rate Limiting & Monitoring

All API responses include rate limiting headers to help you monitor your usage:

Rate Limit Headers

X-RateLimit-Limit: 10000          # Total calls allowed this month
X-RateLimit-Remaining: 9995        # Calls remaining this month  
X-RateLimit-Reset: 2025-10-01T00:00:00Z  # When limit resets
X-RateLimit-Window: monthly         # Rate limit window type

Usage Monitoring

# Check remaining quota
curl -I https://aigc-compliance-api-production.up.railway.app/comply \
  -H "Authorization: Bearer your-api-key"

Code Examples

# Basic compliance request
curl -X POST \
  https://aigc-compliance-api-production.up.railway.app/comply \
  -H "Authorization: Bearer your-api-key" \
  -F "file=@ai-generated-image.jpg" \
  -F "region=EU"

# Advanced request with all options
curl -X POST \
  https://aigc-compliance-api-production.up.railway.app/comply \
  -H "Authorization: Bearer your-api-key" \
  -F "file=@ai-generated-image.jpg" \
  -F "region=CN" \
  -F "include_base64=true" \
  -F "metadata_level=detailed" \
  -F "save_to_disk=true"
import requests

# Basic Python example
def make_compliant(image_path, region="EU"):
    url = "https://aigc-compliance-api-production.up.railway.app/comply"
    headers = {"Authorization": "Bearer your-api-key"}
    
    with open(image_path, 'rb') as f:
        files = {'file': f}
        data = {'region': region}
        
        response = requests.post(url, headers=headers, files=files, data=data)
        return response.json()

# Advanced example with error handling
import requests
from typing import Dict, Optional

class AIGCComplianceClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://aigc-compliance-api-production.up.railway.app"
        self.headers = {"Authorization": f"Bearer {api_key}"}
    
    def make_compliant(self, 
                      image_path: str, 
                      region: str = "EU",
                      include_base64: bool = False,
                      metadata_level: str = "basic") -> Dict:
        """
        Make an image compliant with regional requirements.
        
        Args:
            image_path: Path to image file
            region: "EU" or "CN"
            include_base64: Include base64 encoded result
            metadata_level: "basic" or "detailed"
        
        Returns:
            API response as dictionary
        """
        url = f"{self.base_url}/comply"
        
        with open(image_path, 'rb') as f:
            files = {'file': f}
            data = {
                'region': region,
                'include_base64': str(include_base64).lower(),
                'metadata_level': metadata_level
            }
            
            response = requests.post(url, headers=self.headers, files=files, data=data)
            response.raise_for_status()
            return response.json()
    
    def download_file(self, download_url: str, output_path: str):
        """Download processed file from download URL."""
        response = requests.get(download_url)
        response.raise_for_status()
        
        with open(output_path, 'wb') as f:
            f.write(response.content)

# Usage
client = AIGCComplianceClient("your-api-key")
result = client.make_compliant("ai-image.jpg", region="EU", metadata_level="detailed")
client.download_file(result["download_url"], "compliant-image.png")
// Node.js example with form-data
const FormData = require('form-data');
const fs = require('fs');
const fetch = require('node-fetch');

async function makeCompliant(imagePath, region = 'EU') {
    const form = new FormData();
    form.append('file', fs.createReadStream(imagePath));
    form.append('region', region);
    
    const response = await fetch('https://aigc-compliance-api-production.up.railway.app/comply', {
        method: 'POST',
        headers: {
            'Authorization': 'Bearer your-api-key',
            ...form.getHeaders()
        },
        body: form
    });
    
    return await response.json();
}

// Browser example (requires proxy to avoid CORS)
class AIGCComplianceClient {
    constructor(apiKey) {
        this.apiKey = apiKey;
        this.baseUrl = 'https://aigc-compliance-api-production.up.railway.app';
    }
    
    async makeCompliant(file, region = 'EU', options = {}) {
        const formData = new FormData();
        formData.append('file', file);
        formData.append('region', region);
        
        if (options.includeBase64) {
            formData.append('include_base64', 'true');
        }
        
        if (options.metadataLevel) {
            formData.append('metadata_level', options.metadataLevel);
        }
        
        const response = await fetch(`${this.baseUrl}/comply`, {
            method: 'POST',
            headers: {
                'Authorization': `Bearer ${this.apiKey}`
            },
            body: formData
        });
        
        if (!response.ok) {
            throw new Error(`API Error: ${response.status}`);
        }
        
        return await response.json();
    }
}

// Usage
const client = new AIGCComplianceClient('your-api-key');
const fileInput = document.querySelector('#image-upload');
const file = fileInput.files[0];

client.makeCompliant(file, 'EU', { metadataLevel: 'detailed' })
    .then(result => {
        console.log('Compliance result:', result);
        // Download file automatically
        const a = document.createElement('a');
        a.href = result.download_url;
        a.download = 'compliant-image.png';
        a.click();
    })
    .catch(error => console.error('Error:', error));
apiKey = $apiKey;
    }
    
    public function makeCompliant($imagePath, $region = 'EU', $options = []) {
        $url = $this->baseUrl . '/comply';
        
        $postFields = [
            'file' => new CURLFile($imagePath),
            'region' => $region
        ];
        
        if (isset($options['include_base64'])) {
            $postFields['include_base64'] = $options['include_base64'] ? 'true' : 'false';
        }
        
        if (isset($options['metadata_level'])) {
            $postFields['metadata_level'] = $options['metadata_level'];
        }
        
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $url,
            CURLOPT_POST => true,
            CURLOPT_POSTFIELDS => $postFields,
            CURLOPT_HTTPHEADER => [
                'Authorization: Bearer ' . $this->apiKey
            ],
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT => 30
        ]);
        
        $response = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode !== 200) {
            throw new Exception("API Error: HTTP {$httpCode}");
        }
        
        return json_decode($response, true);
    }
    
    public function downloadFile($downloadUrl, $outputPath) {
        $ch = curl_init();
        curl_setopt_array($ch, [
            CURLOPT_URL => $downloadUrl,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_TIMEOUT => 60
        ]);
        
        $fileContent = curl_exec($ch);
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        curl_close($ch);
        
        if ($httpCode !== 200) {
            throw new Exception("Download Error: HTTP {$httpCode}");
        }
        
        file_put_contents($outputPath, $fileContent);
    }
}

// Usage
$client = new AIGCComplianceClient('your-api-key');

try {
    $result = $client->makeCompliant(
        'ai-generated-image.jpg',
        'EU',
        ['metadata_level' => 'detailed']
    );
    
    echo "Processing successful!\n";
    echo "Download URL: " . $result['download_url'] . "\n";
    
    // Download the processed file
    $client->downloadFile($result['download_url'], 'compliant-image.png');
    echo "File downloaded successfully!\n";
    
} catch (Exception $e) {
    echo "Error: " . $e->getMessage() . "\n";
}
?>

Advanced Integration Examples

Complete examples showcasing the new API capabilities:

React Component with Watermark Customization

import React, { useState } from 'react';

const ImageProcessor = ({ apiKey }) => {
  const [file, setFile] = useState(null);
  const [region, setRegion] = useState('CN');
  const [watermarkText, setWatermarkText] = useState('');
  const [watermarkPosition, setWatermarkPosition] = useState('bottom-right');
  const [logoFile, setLogoFile] = useState(null);
  const [processing, setProcessing] = useState(false);
  const [result, setResult] = useState(null);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setProcessing(true);

    const formData = new FormData();
    formData.append('file', file);
    formData.append('region', region);
    
    if (watermarkText) formData.append('watermark_text', watermarkText);
    if (watermarkPosition) formData.append('watermark_position', watermarkPosition);
    if (logoFile) formData.append('logo_file', logoFile);

    try {
      const response = await fetch('https://aigc-compliance-api-production.up.railway.app/comply', {
        method: 'POST',
        headers: { 'Authorization': `Bearer ${apiKey}` },
        body: formData
      });

      const result = await response.json();
      setResult(result);
    } catch (error) {
      console.error('Processing failed:', error);
    } finally {
      setProcessing(false);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input type="file" onChange={(e) => setFile(e.target.files[0])} required />
      
      <select value={region} onChange={(e) => setRegion(e.target.value)}>
        <option value="EU">EU (C2PA)</option>
        <option value="CN">CN (Watermark)</option>
      </select>

      {region === 'CN' && (
        <>
          <input 
            type="text" 
            placeholder="Custom watermark text"
            value={watermarkText}
            onChange={(e) => setWatermarkText(e.target.value)}
          />
          
          <select value={watermarkPosition} onChange={(e) => setWatermarkPosition(e.target.value)}>
            <option value="bottom-right">Bottom Right</option>
            <option value="bottom-left">Bottom Left</option>
            <option value="top-right">Top Right (Enterprise)</option>
            <option value="top-left">Top Left (Enterprise)</option>
          </select>

          <input 
            type="file" 
            accept="image/png,image/jpeg"
            onChange={(e) => setLogoFile(e.target.files[0])}
            placeholder="Logo file (Professional+)"
          />
        </>
      )}

      <button type="submit" disabled={!file || processing}>
        {processing ? 'Processing...' : 'Process Image'}
      </button>

      {result && (
        <div>
          <h4>Success!</h4>
          <p>Processing time: {result.processing_time_ms}ms</p>
          <a href={result.download_url} download>Download Result</a>
        </div>
      )}
    </form>
  );
};

Python Client with Health Monitoring

import requests
import time
from typing import Optional, Dict, Any

class AIGCComplianceClient:
    def __init__(self, api_key: str, base_url: str = "https://aigc-compliance-api-production.up.railway.app"):
        self.api_key = api_key
        self.base_url = base_url
        self.session = requests.Session()
        self.session.headers.update({"Authorization": f"Bearer {api_key}"})

    def check_health(self) -> Dict[str, Any]:
        """Check API health status"""
        response = requests.get(f"{self.base_url}/health")
        return response.json()

    def process_with_retry(self, image_path: str, region: str, **kwargs) -> Dict[str, Any]:
        """Process image with automatic retry on failure"""
        max_retries = 3
        
        for attempt in range(max_retries):
            try:
                # Check health before processing
                health = self.check_health()
                if health.get("status") != "healthy":
                    raise Exception(f"API unhealthy: {health}")
                
                return self.process_image(image_path, region, **kwargs)
                
            except Exception as e:
                if attempt == max_retries - 1:
                    raise e
                    
                print(f"Attempt {attempt + 1} failed: {e}")
                time.sleep(2 ** attempt)  # Exponential backoff
        
    def process_image(self, image_path: str, region: str, **kwargs) -> Dict[str, Any]:
        """Process image for compliance"""
        files = {'file': open(image_path, 'rb')}
        data = {'region': region, **kwargs}
        
        try:
            response = self.session.post(f"{self.base_url}/comply", files=files, data=data)
            response.raise_for_status()
            return response.json()
        finally:
            files['file'].close()

# Usage example
client = AIGCComplianceClient("your-api-key")

# Check health
health = client.check_health()
print(f"API Status: {health['status']}")

# Process with custom watermark (Professional plan)
result = client.process_with_retry(
    image_path="image.jpg",
    region="CN",
    watermark_text="My Company",
    logo_file=open("logo.png", "rb"),
    watermark_position="bottom-left"
)

SDKs & Libraries

Official SDKs for Python, Node.js, Java, PHP, and more:

Python SDK

pip install aigc-compliance

Node.js SDK

npm install @aigc-compliance/sdk

PHP SDK

composer require aigc-compliance/php-sdk

Java SDK

<dependency>
  <groupId>com.aigc-compliance</groupId>
  <artifactId>aigc-compliance-sdk</artifactId>
  <version>1.0.0</version>
</dependency>

Go SDK

go get github.com/aigc-compliance/go-sdk

Webhooks (Enterprise)

Get real-time notifications when processing completes. Available for Pro and Enterprise plans.

Webhook Payload

{
  "event": "compliance.completed",
  "timestamp": "2025-09-17T12:34:56Z",
  "data": {
    "file_hash": "sha256:a1b2c3d4e5f6789...",
    "region": "EU",
    "status": "success",
    "download_url": "https://aigc-compliance-api-production.up.railway.app/download/...",
    "processing_time_ms": 127,
    "metadata": { ... }
  }
}

Configure webhook endpoints in your dashboard or contact support for API-based webhook management.

C2PA Content Credentials (EU Region)

Our API uses the official c2pa-python 0.25.0 library from the Content Authenticity Initiative (CAI) to provide real C2PA-compliant metadata injection for EU AI Act compliance.

โœ… C2PA Implementation Status

  • Library: Official c2pa-python 0.25.0 from CAI
  • Signing: ES256 (ECDSA P-256) cryptographic algorithm
  • Timestamping: DigiCert Timestamp Authority integration
  • Verification: Manifests validated with CAI Reader
  • Membership: Official CAI member

What is C2PA?

C2PA (Coalition for Content Provenance and Authenticity) is an industry standard for content authenticity and provenance. It embeds cryptographically signed metadata (called "Content Credentials") directly into media files.

How to Use C2PA in Your API Calls

Simply set region=EU in your request - C2PA is automatic:

curl -X POST https://aigc-compliance-api-production.up.railway.app/comply \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -F "file=@image.jpg" \
  -F "region=EU"

# Response includes C2PA info:
{
  "success": true,
  "metadata": {
    "c2pa_signed": true,
    "region_specific_data": {
      "c2pa_info": {
        "c2pa_compliant": true,
        "c2pa_version": "2.0",
        "signed": true,
        "algorithm": "es256",
        "timestamp": "2025-10-25T12:32:10+00:00"
      }
    }
  }
}

Verifying C2PA Content Credentials

Online Tools

Developer Verification

# Install c2pa-python
pip install c2pa-python==0.25.0

# Verify an image
from c2pa import Reader

reader = Reader("processed_image.jpg")
manifest = reader.get_active_manifest()

if manifest:
    print(f"โœ“ Valid C2PA manifest")
    print(f"Creator: {manifest['claim_generator']}")
else:
    print("โœ— No C2PA manifest")

Technical Specifications

Specification Value
C2PA Version 2.0
Library c2pa-python 0.25.0 (official CAI)
Algorithm ES256 (ECDSA P-256)
Format JUMBF (JPEG Universal Metadata Box)

Learn More: Full C2PA Guide | CAI Official Site

Rate Limits

  • Free Plan: 100 API calls total
  • Starter: 10,000 API calls/month
  • Professional: 50,000 API calls/month
  • Enterprise: 500,000 API calls/month

Error Codes Reference

Complete list of error codes and their meanings:

Code Error Type Description Resolution
400 INVALID_REGION Unsupported compliance region Use "EU" or "CN"
400 INVALID_FILE_FORMAT Unsupported image format Use PNG, JPG, JPEG, or WebP
401 UNAUTHORIZED Invalid or missing API key Check Authorization header
403 FORBIDDEN API key lacks permissions Upgrade plan or contact support
413 FILE_TOO_LARGE File exceeds 10MB limit Compress image or use lower resolution
429 RATE_LIMIT_EXCEEDED Monthly quota exhausted Wait for reset or upgrade plan
500 INTERNAL_ERROR Server processing error Retry request or contact support

Best Practices

๐Ÿ”’ Security

  • Never expose API keys in client-side code
  • Use server-side proxy endpoints for browser applications
  • Rotate API keys regularly (quarterly recommended)
  • Monitor rate limit headers to avoid 429 errors

โšก Performance

  • Compress images before upload (max 10MB)
  • Use optimal image formats (PNG for graphics, JPEG for photos)
  • Implement retry logic with exponential backoff
  • Cache download URLs for up to 7 days

๐Ÿ“Š Monitoring

  • Track rate limit headers: X-RateLimit-Remaining
  • Monitor processing times via processing_time_ms
  • Set up alerts for quota usage (>80% recommended)
  • Log file hashes for audit trails

๐ŸŒ Regional Compliance

  • EU (Europe): Visible watermark "AI Generated" + C2PA metadata โ€” Complies with EU AI Act Article 52 (mandatory from 2026)
  • CN (China): Visible watermark + metadata labeling โ€” Complies with CAC Deepfake Regulation (mandatory since 2023)
  • Dual-layer compliance: User-facing (visible watermark) + Technical (C2PA/metadata verification)
  • Test with both regions if targeting global markets
  • Verify compliance metadata in API responses
  • Customize watermark text per plan limits (Free: "AI Generated", Starter: 10 chars, Professional: 20 chars, Enterprise: 50 chars)

Enterprise Features

Advanced capabilities for large-scale deployments:

๐Ÿ”„ Batch Processing

Process up to 100 images in a single request

POST /v1/batch
{
  "images": [
    {"url": "https://example.com/img1.jpg", "region": "EU"},
    {"url": "https://example.com/img2.jpg", "region": "CN"}
  ]
}

๐Ÿ“ก Webhook Integration

Real-time notifications for async processing

POST /v1/webhooks
{
  "url": "https://your-domain.com/webhook",
  "events": ["compliance.completed", "batch.finished"]
}

๐Ÿ” Custom Metadata

Inject custom compliance metadata

POST /comply
{
  "file": "...",
  "region": "EU",
  "custom_metadata": {
    "internal_id": "IMG-2025-001",
    "department": "Marketing",
    "approval_status": "approved"
  }
}

๐Ÿ“ˆ Advanced Analytics

Detailed usage analytics and compliance reports

GET /v1/analytics
{
  "period": "monthly",
  "metrics": ["processing_volume", "compliance_rate", "error_rate"]
}

Contact our sales team for enterprise pricing and custom integrations.

Frequently Asked Questions

Q: How long are download URLs valid?

A: Download URLs expire after 7 days. You should download and store files immediately after processing.

Q: What image formats are supported?

A: We support PNG, JPG, JPEG, and WebP formats up to 10MB per file.

Q: Can I process the same image multiple times?

A: Yes, but each processing request counts toward your monthly quota.

Q: Do you store processed images permanently?

A: No, images are automatically deleted after 30 days for security and privacy.

Q: How do I verify compliance metadata?

A: Use C2PA verification tools for EU compliance or our metadata validation endpoint.

Q: What's the difference between EU and CN processing?

A: EU uses C2PA metadata injection, while CN adds visible/invisible watermarks and content labels.