EaseBG API
AI Background Removal SaaS Platform — Developer API Documentation
High-Performance Inference
Powered by EaseBG v2 model, average processing time < 2 seconds
Batch Processing
Batch background removal with per-request limits by plan (Pro 5 / Business 50 / Enterprise 200 images)
Webhook Callbacks
Async task completion notifications with HMAC-SHA256 signature verification
Multi-Language SDKs
cURL, JavaScript, Python, Go, Java, PHP, Ruby, C#
Basic Information
| Base URL | https://api.easebg.com/api/v1 |
| Local Development | http://localhost:3001/api/v1 |
| Authentication | X-API-Key Header |
| Response Format | JSON |
| Character Encoding | UTF-8 |
Quick Start
Complete your first background removal in 3 steps:
Get Your API Key
Create an API Key in the Developer Center for request authentication.
Create a Task
Upload the image via the presign endpoint first, then create a background removal task with the returned objectKey:
curl -X POST "https://api.easebg.com/api/v1/open/developer/tasks" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"imageUrl": "private-uploads/2026/08/550e8400-photo.jpg"}'
Get the Result
Query the task status and download the result from resultUrl when complete:
curl "https://api.easebg.com/api/v1/open/developer/tasks/TASK_ID" \
-H "X-API-Key: YOUR_API_KEY"
Authentication
EaseBG API supports multiple authentication methods depending on the caller:
| Caller | Method | Header | Path Prefix |
|---|---|---|---|
| External Developers | API Key | X-API-Key: easebg_live_xxx |
/open/developer/* |
| Web/App Frontend | JWT Bearer Token | Authorization: Bearer eyJ... |
/app/* |
Task Processing Flow
The complete flow from upload to result retrieval:
Task Status Flow
Upload Images
The imageUrl used for task creation must be a storage object_key (the inference service cannot fetch external URLs directly), so every image must be uploaded first via the presign endpoint:
# Step 1: Get a presigned upload URL (developer API, API Key auth)
curl -X POST "https://api.easebg.com/api/v1/open/developer/uploads/presign" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"fileName": "photo.jpg", "contentType": "image/jpeg", "fileSize": 204800}'
# Step 2: Upload the file using the returned uploadUrl
curl -X PUT "RETURNED_UPLOAD_URL" \
-H "Content-Type: image/jpeg" \
--data-binary @photo.jpg
# objectKey is now ready: use it as imageUrl when creating a task
/app/tasks/uploads/presign endpoint; the flow is identical.
Supported Image Formats
| Format | MIME Type | Max Size |
|---|---|---|
| PNG | image/png | 20 MB |
| JPEG | image/jpeg | 20 MB |
| WebP | image/webp | 20 MB |
Create Task
imageUrl must be a storage object_key (the inference service cannot fetch external URLs directly). Call POST /open/developer/uploads/presign first, PUT the file to the returned uploadUrl, then pass the returned objectKey as imageUrl.
# Step 1: Get a pre-signed upload URL
curl -X POST "https://api.easebg.com/api/v1/open/developer/uploads/presign" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "fileName": "photo.jpg", "contentType": "image/jpeg", "fileSize": 204800 }'
# → { "data": { "uploadUrl": "...", "objectKey": "private-uploads/2026/...", "method": "PUT", ... } }
# Step 2: Upload the file directly (PUT to uploadUrl)
# Step 3: Create a task with the objectKey
curl -X POST "https://api.easebg.com/api/v1/open/developer/tasks" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"imageUrl": "private-uploads/2026/08/550e8400-photo.jpg",
"modelVersion": "easebg-v2",
"callbackUrl": "https://your-app.com/webhooks/easebg"
}'
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
imageUrl | string | Yes | Storage object_key of the image, obtained via the presign upload endpoint |
modelVersion | string | No | Model version brand identifier (currently easebg-v2, i.e. EaseBG v2); invalid values return 400; omitted = platform default |
callbackUrl | string (uri) | No | Webhook callback URL |
Sync vs Async
By default, tasks run in async mode and return a queued status immediately. For synchronous waiting, poll GET /tasks/{taskId} or configure a webhook callback for completion notifications.
Query Task
Query processing status and results by task ID:
curl "https://api.easebg.com/api/v1/open/developer/tasks/TASK_ID" \
-H "X-API-Key: YOUR_API_KEY"
Response Example (Processing)
{
"request_id": "req_abc123",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "processing",
"modelVersion": "easebg-v2",
"sourceUrl": "private-uploads/2026/08/550e8400-photo.jpg",
"resultUrl": null,
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": null
}
}
Response Example (Completed)
{
"request_id": "req_abc123",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "succeeded",
"modelVersion": "easebg-v2",
"sourceUrl": "private-uploads/2026/08/550e8400-photo.jpg",
"resultUrl": "https://storage.easebg.com/results/550e8400.png",
"durationMs": 1200,
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": "2025-01-15T10:30:01.2Z"
}
}
Event Stream Query (Near Real-Time)
Poll the event history endpoint to retrieve events that occurred during task processing:
// Poll task event history (JWT auth via Authorization header)
async function pollTaskEvents(taskId, accessToken, intervalMs = 2000) {
const seen = new Set();
const timer = setInterval(async () => {
const res = await fetch(
`https://api.easebg.com/api/v1/app/tasks/images/${taskId}/events`,
{ headers: { Authorization: `Bearer ${accessToken}` } }
);
const { data: events } = await res.json();
for (const ev of events) {
if (!seen.has(ev.id)) {
seen.add(ev.id);
console.log('Event:', ev.event_type, ev.event_payload);
if (ev.event_type === 'succeeded' || ev.event_type === 'failed' || ev.event_type === 'canceled' || ev.event_type === 'dead_letter' || ev.event_type === 'dead_lettered') {
clearInterval(timer);
}
}
}
}, intervalMs);
}
GET /api/v1/app/tasks/images/{taskId} and stop once the task reaches a terminal state (succeeded / failed). Developer API users can combine this with Webhook notifications to avoid polling.
Download Result
After task completion, retrieve the result via the following methods:
Method 1: Direct from Response
When querying task details, the resultUrl field contains the result image URL for direct download.
# Download the result image
curl -o result.png "https://storage.easebg.com/results/550e8400.png"
Method 2: Get Download URL (App API)
For App/Web frontend, use the dedicated download endpoint to get a time-limited download URL:
curl "https://api.easebg.com/api/v1/app/tasks/images/TASK_ID/download" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
Tasks API
Image processing task endpoints, supporting upload, creation, querying, cancellation, and retry.
/open/developer/uploads/presign
Tasks
Get Presigned Upload URL
imageUrl for task creation must be a storage object_key. Call this endpoint to get a direct upload URL, PUT the file, then pass the returned objectKey as imageUrl.
/open/developer/tasks
Tasks
Create Background Removal Task
Submit an image for background removal. Supports both synchronous waiting and async callback modes.
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
imageUrl | string | Yes | Storage object_key of the image, obtained via the presign upload endpoint |
modelVersion | string | No | Model version brand identifier (currently easebg-v2, i.e. EaseBG v2); invalid values return 400; omitted = platform default |
callbackUrl | string (uri) | No | Webhook callback URL (http/https only) |
Response Example
{
"request_id": "req_abc123",
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"status": "queued",
"modelVersion": "easebg-v2",
"sourceUrl": "private-uploads/2026/08/550e8400-photo.jpg",
"resultUrl": null,
"creditCost": 1,
"createdAt": "2025-01-15T10:30:00Z",
"completedAt": null
}
}
Error Codes
| HTTP | Error Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS | Invalid request parameters (including invalid modelVersion) |
| 401 | API_KEY_MISSING | API key is missing |
| 401 | API_KEY_INVALID | Invalid API key |
| 403 | API_KEY_INSUFFICIENT_SCOPE | API key lacks required scope |
| 400 | CREDITS_INSUFFICIENT | Insufficient credits |
| 403 | TASK_INPUT_FORBIDDEN | Input file not found or not owned by current user |
| 400 | TASK_FILE_SIZE_EXCEEDED | File size exceeds plan limit |
| 400 | TASK_FORMAT_NOT_SUPPORTED | Image format not allowed for your plan |
| 400 | TASK_CONCURRENT_LIMIT | Concurrent task limit reached |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit exceeded |
| 429 | DEVELOPER_API_QUOTA_EXCEEDED | Monthly API quota exceeded |
| 503 | TASK_MAINTENANCE | System maintenance in progress |
/open/developer/tasks
Tasks
List Tasks
Get the task list for the current API user, supporting pagination and status filtering.
Query Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
pageSize | integer | 20 | Items per page, max 100 |
status | string | - | Filter: queued, processing, succeeded, failed, canceled |
startDate | date | - | Start date |
endDate | date | - | End date |
/open/developer/tasks/{taskId}
Tasks
Get Task Details
Get task details by ID, including the result URL.
/open/developer/tasks/{taskId}
Tasks
Cancel Task
Cancel a queued task. Completed or processing tasks cannot be canceled.
/open/developer/tasks/{taskId}/retry
Tasks
Retry Task
Resubmit a failed task for processing.
Batch API
Batch processing endpoints. The per-request limit depends on your plan: Pro 5, Business 50, Enterprise 200 images (exceeding it returns 400 TASK_BATCH_SIZE_EXCEEDED).
/open/developer/batch-tasks
Batch
Create Batch Task
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
imageUrls | string[] | Yes | Array of storage object_keys, obtained via the presign upload endpoint; per-request limit by plan: Pro 5 / Business 50 / Enterprise 200 |
modelVersion | string | No | Model version brand identifier (currently easebg-v2, i.e. EaseBG v2); invalid values return 400; omitted = platform default |
callbackUrl | string (uri) | No | Webhook callback URL |
/open/developer/batch-tasks
Batch
List Batch Tasks
/open/developer/batch-tasks/{batchId}
Batch
Get Batch Task Details
Webhooks API
/open/developer/webhooks
Webhook
List Webhook Endpoints
/open/developer/webhooks
Webhook
Create Webhook Endpoint
Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
targetUrl | string (uri) | Yes | Webhook receiver URL (http/https only, private network addresses rejected) |
eventTypes | string[] | No | List of subscribed events, defaults to an empty array |
Developer API
/open/developer/api-keys
Developer
List API Keys
/open/developer/usage
Developer
Get Usage Statistics
Get usage statistics for the current user (total/succeeded/failed tasks, credit consumption, API requests, average latency, error rate, monthly quota) plus a 30-day daily trend.
App API Reference
Frontend-facing endpoints for Web/App, using JWT Bearer Token authentication.
| Module | Path Prefix | Key Endpoints |
|---|---|---|
| Auth | /app/auth/* | Register, Login, 2FA, Password, Email verification |
| User | /app/users/* | Profile, Subscription, Login history |
| Tasks | /app/tasks/* | Create, Query, Batch, Retry, Download |
| Credits | /app/credits/* | Balance, Ledger, Expiry alerts |
| Payments | /app/payments/* | Orders, Refunds, Invoices, Subscriptions |
| Notifications | /app/notifications/* | List, Unread count, Mark read |
| Referral | /app/referral/* | Referral info, Invitation records |
| Teams | /app/teams/* | Members, Invites, Credits, Billing |
openapi-app.json for the complete App API contract.
Webhook Overview
When a subscribed event occurs (tasks, credits, payments, subscriptions, refunds, security, etc.), EaseBG sends a POST request to your configured webhook URL.
event plus the business ID (e.g. task_id, order_id) for idempotent processing.
Request Format
POST /your-webhook-endpoint HTTP/1.1
Host: your-app.com
Content-Type: application/json
X-EaseBG-Signature: t=1736937005,v1=a1b2c3d4e5f6...
{
"event": "task.succeeded",
"task_id": "550e8400-e29b-41d4-a716-446655440000",
"message": "Task completed successfully"
}
Webhook Event List
| Event | Trigger | Payload Fields |
|---|---|---|
task.succeeded |
Task processing succeeded | task_id, message |
task.failed |
Task processing failed | task_id, reason, message |
task.retention_cleanup |
History tasks cleaned up after retention period | count, days, message |
batch.completed |
All batch tasks completed | batch_job_id, total_count, success_count, failed_count, message |
credits.low_balance |
Credit balance below threshold | balance, message |
credits.refunded |
Credits reversed (e.g. refund revocation) | amount, message |
credits.pack_purchased |
Credit pack purchased | credits, pack_name, message |
credits.expiration_warning |
Credits about to expire | credits, expiry_date, message |
payment.succeeded |
Payment succeeded | order_id, amount, currency, message |
payment.failed |
Payment failed | order_id, message |
refund.succeeded |
Refund processed successfully | refund_id, order_id, amount, currency, message |
subscription.updated |
Subscription activated or changed | plan, message |
subscription.canceled |
Subscription canceled (at period end) | period_end, message |
subscription.renewed |
Subscription renewed | plan_name, period_end, message |
referral.reward |
Referral reward granted | credits, description, message |
team.invitation |
Team invitation received | team_name, inviter_email, role, invite_url, message |
welcome |
New user welcome | message |
security.password_changed |
Password changed | message |
security.mfa_enabled |
MFA enabled | message |
security.mfa_disabled |
MFA disabled | message |
Webhook Signature Verification
Each webhook request carries an X-EaseBG-Signature header (format: t=<timestamp>,v1=<signature>). The signature is computed over <timestamp>.<raw body> using HMAC-SHA256.
Signature Algorithm
const crypto = require('crypto');
// header: 't=1736937005,v1=a1b2c3d4...'
function verifySignature(rawBody, header, secret) {
if (!header) return false; // header absent -> reject, don't throw
const match = /^t=(\d+),v1=([a-f0-9]+)$/.exec(header);
if (!match) return false;
const [, timestamp, signature] = match;
const computed = crypto
.createHmac('sha256', secret)
.update(`${timestamp}.${rawBody}`, 'utf8')
.digest('hex');
const computedBuffer = Buffer.from(computed, 'hex');
const signatureBuffer = Buffer.from(signature, 'hex');
// timingSafeEqual throws RangeError when buffer lengths differ, so guard first
if (computedBuffer.length !== signatureBuffer.length) return false;
return crypto.timingSafeEqual(computedBuffer, signatureBuffer);
}
timingSafeEqual) to verify signatures and prevent timing attacks.
Webhook Retry Strategy
If your server returns a non-2xx status code or times out, the system retries automatically with exponential backoff (2^n minutes, capped at 60 minutes):
| Attempt | Delay |
|---|---|
| 1st | 2 min |
| 2nd | 4 min |
| 3rd | 8 min |
| 4th | 16 min |
| 5th and later | 32 / 60 / 60 min … |
After exceeding the configured maximum retry count, the event is marked as permanently failed.
Webhook Test & Debug
In the Developer Center, each webhook endpoint card has a "Test" button that sends a test event to your target URL to verify connectivity and signature verification.
Test Event
{
"event": "test.webhook",
"timestamp": "2025-01-15T10:30:05.000Z",
"data": {
"message": "This is a test webhook event from EaseBG v2 developer center.",
"endpoint_id": "your-endpoint-id"
}
}
Test events use the same signature algorithm as real events (t=<timestamp>,v1=<hex>, HMAC-SHA256 over timestamp.body).
Debug Tips
- Use RequestBin or webhook.site as a temporary receiver for debugging
- Verify that the
X-EaseBG-Signatureheader matches your locally computed signature - Ensure your server returns a
2xxstatus code, otherwise exponential-backoff retries will be triggered - Use
eventplus the business ID (e.g.task_id,order_id) for idempotent processing to avoid handling the same event twice
Idempotency Example
// Idempotent handling example
async function handleWebhook(req, res) {
const { event, task_id, order_id } = req.body;
// Use event type + business ID as the idempotency key (payload has no global event ID)
const eventKey = `${event}:${task_id || order_id || ''}`;
// Check if event was already processed
const exists = await db.query(
'SELECT 1 FROM processed_webhook_events WHERE event_key = $1',
[eventKey]
);
if (exists) {
return res.status(200).json({ ok: true, message: 'already processed' });
}
// Process the event
await processEvent(event, task_id || order_id);
// Record as processed
await db.query(
'INSERT INTO processed_webhook_events (event_key, event_type) VALUES ($1, $2)',
[eventKey, event]
);
res.status(200).json({ ok: true });
}
Error Codes
All error responses use the following unified format:
{
"request_id": "req_abc123",
"error": {
"code": "DEVELOPER_TASK_NOT_FOUND",
"message": "Task not found",
"details": {}
}
}
| HTTP | Error Code | Description |
|---|---|---|
| 400 | INVALID_PARAMS | Invalid request parameters (including invalid modelVersion) |
| 401 | API_KEY_MISSING | API key is missing |
| 401 | API_KEY_INVALID | Invalid API key |
| 401 | AUTH_INVALID_TOKEN | Invalid or expired JWT token |
| 400 | CREDITS_INSUFFICIENT | Insufficient credits |
| 403 | API_KEY_INSUFFICIENT_SCOPE | API key lacks required scope |
| 403 | AUTH_FORBIDDEN | Access forbidden |
| 403 | DEVELOPER_API_ACCESS_DENIED | Current plan does not support API access |
| 503 | TASK_MAINTENANCE | System maintenance in progress, new task submission paused |
| 400 | TASK_BATCH_DISABLED | Batch processing is disabled by the administrator |
| 400 | TASK_BATCH_NOT_SUPPORTED | Current plan does not support batch processing |
| 400 | TASK_BATCH_SIZE_EXCEEDED | Batch size exceeds plan limit (Pro 5 / Business 50 / Enterprise 200) |
| 403 | TASK_INPUT_FORBIDDEN | Input file not found or not owned by current user |
| 400 | TASK_FILE_SIZE_EXCEEDED | File size exceeds plan limit |
| 400 | TASK_FORMAT_NOT_SUPPORTED | Image format not allowed for your plan |
| 400 | TASK_OUTPUT_FORMAT_NOT_SUPPORTED | Output format not allowed for your plan |
| 400 | TASK_CONCURRENT_LIMIT | Concurrent task limit reached |
| 400 | TASK_NOT_RETRYABLE | Task cannot be retried in current state |
| 400 | TASK_RETRY_LIMIT_EXCEEDED | Max retry limit reached |
| 503 | TASK_STORAGE_UNAVAILABLE | Storage service unavailable (presign upload) |
| 404 | DEVELOPER_TASK_NOT_FOUND | Task not found |
| 404 | DEVELOPER_BATCH_NOT_FOUND | Batch task not found |
| 404 | NOT_FOUND | Resource not found |
| 409 | CONFLICT | State conflict |
| 409 | TASK_CANNOT_CANCEL | Task cannot be canceled in current state |
| 429 | RATE_LIMIT_EXCEEDED | Rate limit exceeded |
| 429 | DEVELOPER_API_QUOTA_EXCEEDED | Monthly API quota exceeded |
| 500 | SYSTEM_INTERNAL_ERROR | Internal server error |
Rate Limits & Quotas
API access, monthly quota and rate limits are tiered by plan (the Free plan does not include API access):
| Plan | API Access | Monthly API Quota | Concurrent Tasks | Batch Limit | Requests/min |
|---|---|---|---|---|---|
| Free | No | - | 1 | - | 600 |
| Pro | Yes | 1,000 | 2 | 5 | 1,200 |
| Business | Yes | 10,000 | 3 | 50 | 2,400 |
| Enterprise | Yes | 50,000 | 4 | 200 | 6,000 |
When the limit is exceeded, a 429 status code is returned with the following headers:
X-RateLimit-Limit: 1200
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1736940660
Retry-After: 60
SDK Examples
Complete example code is available in the following languages:
Postman Collection
Import the Postman collection to quickly start testing the API:
Changelog
Breaking Changes
- Unified API path prefix to
/api/v1 - Layered authentication: API Key / JWT
- Unified error response format
- Task event history endpoint (polling mode)
New Endpoints
- Tasks API (create, query, cancel, retry)
- Batch API (batch processing)
- Webhooks API (endpoint management)
- Developer API (API Key, usage stats)
- App API (register, login, user center, etc.)
Deprecated
- Legacy
/v1/tasksendpoints marked as deprecated
Deprecated APIs
| Deprecated | Replacement | Since | Removal |
|---|---|---|---|
GET /v1/tasks | GET /api/v1/open/developer/tasks | v2.0 | v3.0 |
POST /v1/tasks | POST /api/v1/open/developer/tasks | v2.0 | v3.0 |
GET /v1/tasks/{id} | GET /api/v1/open/developer/tasks/{taskId} | v2.0 | v3.0 |
DELETE /v1/tasks/{id} | DELETE /api/v1/open/developer/tasks/{taskId} | v2.0 | v3.0 |