Most document processing operations in DeckFlow—such as generation, translation, revamp, and format conversion—are computationally intensive. To ensure immediate API responses, DeckFlow utilizes an asynchronous task execution model.
After submitting a task (POST /tools/tasks), developers can retrieve the final results using three different methods: SSE Real-time Subscription (Server-Sent Events), API Polling (Polling), and Webhook Callbacks (Webhook Callback).
1. Comparison of Status Retrieval Methods
To help you choose the best integration pattern, the following table compares the advantages and disadvantages of SSE real-time stream subscription and periodic polling:
| Method | Recommendation | Pros | Cons | Ideal Use Cases |
|---|---|---|---|---|
| SSE Real-time Subscription (Server-Sent Events) | Recommended (Highly Recommended) | Extremely real-time; lightweight and resource-efficient (single HTTP connection); no need for repeated connection establishment; server pushes updates automatically. | Requires client support for stream response parsing; developers need to implement reconnect logic for network disruptions. | Web/client applications, CLI automation scripts, and front-end interfaces requiring live progress feedback. |
| API Periodic Polling (Polling) | Backup / Fallback Only | Simple to implement; natively supported by all HTTP clients; no streaming requirements on the client environment. | Higher latency; repeated requests consume substantial network bandwidth and server resources, making it prone to triggering 429 rate limits. |
Simple backend background jobs, or restricted environments where long-lived connections cannot be maintained. |
2. Server-Sent Events (SSE) Real-time Subscription
When a client queries the task status, sending a specific HTTP header will instruct the DeckFlow server to upgrade the connection to an SSE real-time data stream.
API Specification
- Request Path:
GET /tools/tasks/{taskId} - Required Header:
response-event-stream: yes(must be set toyesto enable SSE mode)
Code Examples
# Retrieve live progress updates via curl
curl -X GET "https://app.deckflow.com/api/tools/tasks/YOUR_TASK_ID" \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "response-event-stream: yes"
const taskId = "YOUR_TASK_ID";
const url = `https://app.deckflow.com/api/tools/tasks/${taskId}`;
async function subscribeTaskSSE() {
const response = await fetch(url, {
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'response-event-stream': 'yes'
}
});
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n');
for (const line of lines) {
if (line.startsWith('data:')) {
const task = JSON.parse(line.replace('data:', '').trim());
console.log('Received progress update:', task.status);
if (task.status === 'completed') {
console.log('Task completed! Download URL:', task.result.url);
return;
} else if (task.status === 'failed') {
console.error('Task failed. Error details:', task.error);
return;
}
}
}
}
}
subscribeTaskSSE();
import requests, json
task_id = "YOUR_TASK_ID"
url = f"https://app.deckflow.com/api/tools/tasks/{task_id}"
headers = {
"Authorization": "Bearer <YOUR_API_KEY>",
"response-event-stream": "yes"
}
def subscribe_task_sse():
response = requests.get(url, headers=headers, stream=True)
for line in response.iter_lines():
if line:
decoded_line = line.decode('utf-8')
if decoded_line.startswith('data:'):
task = json.loads(decoded_line.replace('data:', '').strip())
print("Received progress update:", task.get("status"))
if task.get("status") == "completed":
print("Task completed! Download URL:", task["result"]["url"])
break
elif task.get("status") == "failed":
print("Task failed. Error details:", task.get("error"))
break
subscribe_task_sse()
3. API Periodic Polling (Polling)
When using the polling pattern, the client submits multiple separate HTTP requests to the task status endpoint.
API Specification
- Request Path:
GET /tools/tasks/{taskId} - Required Header:
Authorization: Bearer <YOUR_API_KEY>
Polling Guidelines
- Exponential Backoff: Start with an initial interval of about 3 seconds. Gradually increase the delay between attempts (e.g., 3s -> 5s -> 10s -> 20s) as time passes to avoid rate limits (
429 Rate Limit). - Hard Timeout boundaries: Establish a maximum polling duration (such as 5 minutes). If the task does not finish within this duration, terminate the polling and handle the timeout.
Code Examples
const taskId = "YOUR_TASK_ID";
const url = `https://app.deckflow.com/api/tools/tasks/${taskId}`;
const headers = { 'Authorization': 'Bearer <YOUR_API_KEY>' };
async function pollTaskStatus() {
let delay = 3000; // Start with a 3-second delay
const maxDelay = 30000; // Cap delay at 30 seconds
while (true) {
const res = await fetch(url, { headers });
const task = await res.json();
console.log('Polling status:', task.status);
if (task.status === 'completed') {
console.log('Task succeeded. Download URL:', task.result.url);
break;
} else if (task.status === 'failed') {
console.error('Task failed. Reason:', task.error);
break;
}
// Exponential backoff wait
await new Promise(resolve => setTimeout(resolve, delay));
delay = Math.min(delay * 1.5, maxDelay);
}
}
pollTaskStatus();
import requests, time
task_id = "YOUR_TASK_ID"
url = f"https://app.deckflow.com/api/tools/tasks/{task_id}"
headers = { "Authorization": "Bearer <YOUR_API_KEY>" }
def poll_task_status():
delay = 3.0 # Start with 3 seconds
max_delay = 30.0
while True:
response = requests.get(url, headers=headers)
task = response.json()
status = task.get("status")
print("Polling status:", status)
if status == "completed":
print("Task succeeded. Download URL:", task["result"]["url"])
break
elif status == "failed":
print("Task failed. Reason:", task.get("error"))
break
time.sleep(delay)
delay = min(delay * 1.5, max_delay)
poll_task_status()
4. Webhook Callbacks
For integrations that prefer to avoid active polling or streaming (such as background offline batch jobs), DeckFlow can push the final task status to your server using Webhook callbacks.
Configuration
Submit the task (POST /tools/tasks) with a notifyURL parameter in the Form Data body, containing the publicly reachable HTTP URL of your listener endpoint.
Payload & Lifecycle
When the task reaches its final state (completed or failed), DeckFlow will dispatch an HTTP POST request to your notifyURL.
- Payload Format:
application/json - Payload Structure: The complete Task entity JSON object.
Callback Body Example:
{
"id": "task-550e8400-e29b-41d4-a716-446655440000",
"name": "Market Research Slide Revamp",
"type": "revamp",
"status": "completed",
"result": {
"url": "https://app.deckflow.com/download/processed-presentation.pptx?...",
"mimeType": "application/vnd.openxmlformats-officedocument.presentationml.presentation"
},
"createdAt": "2026-06-11T08:52:00.000Z",
"updatedAt": "2026-06-11T08:54:15.000Z"
}