Manual approval today, cleaner self-serve later
- Tell us about your integration and the conversion volume you expect.
- We review the use case and manually approve early API access when it fits.
- Use the API to submit jobs and poll for outputs.
Submit conversion jobs, check tracked outputs, and review workspace usage through a Pro-only API designed for practical early integrations.
Per active API key on the current workspace plan.
Job submission ceiling for the current workspace plan.
Manual API key issuance is tied to approved Pro workspaces.
Authentication uses `X-API-Key` or `Authorization: Bearer`.
POST /api/v1/jobs submits a tracked conversion job.GET /api/v1/jobs/{requestId} returns job state and download links.GET /api/v1/usage returns workspace and API-specific usage.Use multipart form data with an API key tied to an approved Pro workspace.
curl -X POST "https://wonderconvert.com/api/v1/jobs" \
-H "X-API-Key: wc_your_key_here" \
-H "Idempotency-Key: invoice-2026-03-12-run-001" \
-F "conversion_type=image" \
-F "from=png" \
-F "to=jpg" \
-F "webhook_url=https://client.example/webhooks/wonderconvert" \
-F "webhook_secret=client_shared_secret" \
-F "total_files=1" \
-F "total_size=0.25" \
-F "files[][email protected]"
{
"status": 202,
"message": "Your files are being processed.",
"job_id": 481,
"request_id": "req_xxxxx",
"job_status_url": "https://wonderconvert.com/api/v1/jobs/req_xxxxx"
}
{
"status": 200,
"workspace": {
"slug": "api-workspace"
},
"job": {
"request_id": "req_xxxxx",
"status": "completed",
"conversion_type": "image",
"source_format": "png",
"target_format": "jpg"
},
"outputs": [
{
"file_name": "output.jpg",
"download_url": "https://..."
}
]
}
curl "https://wonderconvert.com/api/v1/jobs/req_xxxxx" \
-H "Authorization: Bearer wc_your_key_here"
The response includes status, conversion metadata, and time-limited download URLs for completed outputs.
curl "https://wonderconvert.com/api/v1/usage" \
-H "X-API-Key: wc_your_key_here"
The usage response now includes both total workspace activity and API-only usage, plus lifecycle counts for submitted, pending, processing, completed, and failed API jobs.
This is the simplest safe pattern if you do not want to rely on webhooks yet.
const apiKey = process.env.WONDERCONVERT_API_KEY;
async function submitAndPoll(formData) {
const createResponse = await fetch("https://wonderconvert.com/api/v1/jobs", {
method: "POST",
headers: {
"X-API-Key": apiKey,
"Idempotency-Key": `job-${Date.now()}`
},
body: formData
});
const created = await createResponse.json();
let statusUrl = created.job_status_url;
while (true) {
const statusResponse = await fetch(statusUrl, {
headers: { "X-API-Key": apiKey }
});
const status = await statusResponse.json();
if (status.job.status === "completed") return status.outputs;
if (status.job.status === "failed") throw new Error(status.job.error_message);
await new Promise(resolve => setTimeout(resolve, 3000));
}
}
Include `webhook_url` and optionally `webhook_secret` on job submission. WonderConvert sends signed JSON payloads with `X-WonderConvert-Event`, `X-WonderConvert-Request-Id`, and `X-WonderConvert-Signature` headers.
{
"event": "conversion.job.completed",
"workspace": {
"slug": "api-workspace"
},
"job": {
"request_id": "req_xxxxx",
"status": "completed",
"idempotency_key": "invoice-2026-03-12-run-001"
},
"outputs": [
{
"file_name": "output.jpg",
"download_url": "https://..."
}
]
}
$rawBody = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $rawBody, $sharedSecret);
$received = $_SERVER['HTTP_X_WONDERCONVERT_SIGNATURE'] ?? '';
if (!hash_equals($expected, $received)) {
http_response_code(401);
exit('Invalid signature');
}
This lets you trust that the webhook payload came from WonderConvert and was not modified in transit.
php artisan api:replay-job-webhook req_xxxxx
# Optional event override
php artisan api:replay-job-webhook req_xxxxx \
--event=conversion.job.completed
# Batch replay recent failed webhook jobs
php artisan api:replay-failed-webhooks --limit=25
Webhook delivery state, retry timing, attempt history, and the last delivery error are visible on the job detail page inside the dashboard.