Tasks
AI products rarely bill for a single, isolated action. In practice, a customer's work is a sequence of steps: a script gets drafted, a video gets rendered, subtitles get generated, translations get applied. Each step produces a usage event. Each event has its own cost. Taken individually, these events tell you what happened. Taken together, they tell you whether a deliverable was profitable.
Tasks are Credyt's way of holding that whole picture in one place.
A task is the collection of all usage events that share the same subject for a given customer - automatically assembled and continuously updated as new events arrive. There's no separate resource to create. If you're already including a subject field on your usage events, tasks are already forming in the background.
How tasks work
API Reference — List Tasks · API Reference — Get a Task
The subject field on a usage event is a string you define. It's intended to identify the activity your customer is performing - a video job, a chat session, a document workflow, an autonomous agent run. When multiple events share the same customer and subject, Credyt treats them as a single task.
A task accumulates:
- All events in the order they occurred, with their individual fees, costs, and stats
- Aggregated profitability stats across the full set of events: gross revenue, total costs, net revenue, and margin
- A per-vendor cost breakdown, showing how much each external service contributed to total costs
Tasks are read-only views - they don't require you to open or close anything. As long as events continue arriving with the same subject, the task continues to grow.
The task identifier is derived directly from the customer and subject: {customer_id}:{subject}. When querying the task detail endpoint, URL-encode the identifier before passing it as a path parameter — for example, cust_47yxefzbfwkxragp01ccce965n%3Avideo_gen_a7c23f91.
Tasks and the subject field
If you haven't used subject in your events yet, see the Usage Events guide. The recommendation is to include a subject for every event, and this matters primarily because of tasks.
Subjects work best when they map to an outcome your customer cares about - not an internal process step. For a video generation platform, the subject might be video_gen_a7c23f91. For a customer support agent, it might be ticket_89423. For a podcast production tool, it might be episode_s02e11. The subject should be stable across all the events that together constitute the delivery of that outcome.
A task spans as many events as it takes to complete the deliverable. If a workflow involves three LLM calls, a rendering job, and a post-processing step, all five events under the same subject form one task. Credyt doesn't impose any limit on the number of events per task.
Example
GlitchAI: a video production job
GlitchAI is a video generation platform. When a customer submits a video request, GlitchAI runs a pipeline: a language model generates a script, a video model renders the footage, a transcription model produces subtitles, and a translation service localises the output. Each of these steps produces a usage event. All of them carry the same subject, the ID of the video job.
Not every event in a task needs to generate a billing fee. GlitchAI charges its customers for three specific outcomes - video generation, subtitle generation, and translation - and only those event types are configured with a matching price in the product catalog. The script generation step produces an event but no fee. GlitchAI treats it as a cost of producing the video, bundled into the overall economics of the job rather than passed through as a separate line item.
However, GlitchAI still submits costs for the scripting step. Even when an event carries no fee, the cost data it contains flows into the task's profitability calculation. This is where tasks become particularly powerful for internal analysis: by tracking what each intermediate step actually costs to run - regardless of whether it's billed for - the platform gets a complete picture of its unit economics. If the scripting step starts consuming significantly more tokens than expected, it will appear in the task's cost breakdown, even though customers never see a charge for it. This makes cost-annotated intermediate events a useful signal for detecting loops, unexpected retries, or model behaviour that drifts outside normal parameters.
Here's what those events look like as they are submitted:
POST https://api.credyt.ai/events
- REST API
- TypeScript SDK
- Python SDK
{
"customer_id": "cust_47yxefzbfwkxragp01ccce965n",
"events": [
{
"id": "b1b2c3d4-0001-4000-8000-000000000001",
"event_type": "script_generated",
"occurred_at": "2026-05-28T11:50:00Z",
"subject": "video_gen_a7c23f91",
"description": "Script generation completed",
"costs": [
{
"id": "c1000000-0001-4000-8000-000000000001",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "GPT-4o script generation",
"amount": 0.0043,
"currency": "USD"
}
],
"data": {
"model": "gpt-4o",
"input_tokens": 512,
"output_tokens": 1840
}
},
{
"id": "b1b2c3d4-0002-4000-8000-000000000002",
"event_type": "video_generated",
"occurred_at": "2026-05-28T11:51:48Z",
"subject": "video_gen_a7c23f91",
"description": "Video generation completed",
"costs": [
{
"id": "c1000000-0002-4000-8000-000000000002",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "Sora video generation (fast, 1080p)",
"amount": 0.32,
"currency": "USD"
}
],
"data": {
"model": "sora-fast",
"speed": "fast",
"minutes": 2
}
},
{
"id": "b1b2c3d4-0003-4000-8000-000000000003",
"event_type": "subtitles_generated",
"occurred_at": "2026-05-28T11:53:12Z",
"subject": "video_gen_a7c23f91",
"description": "Subtitle generation completed",
"costs": [
{
"id": "c1000000-0003-4000-8000-000000000003",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "Whisper transcription",
"amount": 0.0048,
"currency": "USD"
}
],
"data": {
"model": "whisper-1",
"audio_minutes": 2
}
},
{
"id": "b1b2c3d4-0004-4000-8000-000000000004",
"event_type": "translation_completed",
"occurred_at": "2026-05-28T11:54:51Z",
"subject": "video_gen_a7c23f91",
"description": "Subtitle translation completed",
"costs": [
{
"id": "c1000000-0004-4000-8000-000000000004",
"vendor_id": "vnd_4r349d2m72m7r2jx68z20tswx2",
"description": "DeepL translation",
"amount": 0.0052,
"currency": "USD"
}
],
"data": {
"characters": 2600
}
}
]
}
await client.events.sendUsage({
customerId: "cust_47yxefzbfwkxragp01ccce965n",
events: [
{
id: "b1b2c3d4-0001-4000-8000-000000000001",
eventType: "script_generated",
occurredAt: "2026-05-28T11:50:00Z",
subject: "video_gen_a7c23f91",
description: "Script generation completed",
costs: [
{
id: "c1000000-0001-4000-8000-000000000001",
vendorId: "vnd_4c22r59kkbz0z2cnntdksn7t45",
description: "GPT-4o script generation",
amount: 0.0043,
currency: "USD",
},
],
data: {
model: "gpt-4o",
inputTokens: 512,
outputTokens: 1840,
},
},
{
id: "b1b2c3d4-0002-4000-8000-000000000002",
eventType: "video_generated",
occurredAt: "2026-05-28T11:51:48Z",
subject: "video_gen_a7c23f91",
description: "Video generation completed",
costs: [
{
id: "c1000000-0002-4000-8000-000000000002",
vendorId: "vnd_4c22r59kkbz0z2cnntdksn7t45",
description: "Sora video generation (fast, 1080p)",
amount: 0.32,
currency: "USD",
},
],
data: {
model: "sora-fast",
speed: "fast",
minutes: 2,
},
},
{
id: "b1b2c3d4-0003-4000-8000-000000000003",
eventType: "subtitles_generated",
occurredAt: "2026-05-28T11:53:12Z",
subject: "video_gen_a7c23f91",
description: "Subtitle generation completed",
costs: [
{
id: "c1000000-0003-4000-8000-000000000003",
vendorId: "vnd_4c22r59kkbz0z2cnntdksn7t45",
description: "Whisper transcription",
amount: 0.0048,
currency: "USD",
},
],
data: {
model: "whisper-1",
audioMinutes: 2,
},
},
{
id: "b1b2c3d4-0004-4000-8000-000000000004",
eventType: "translation_completed",
occurredAt: "2026-05-28T11:54:51Z",
subject: "video_gen_a7c23f91",
description: "Subtitle translation completed",
costs: [
{
id: "c1000000-0004-4000-8000-000000000004",
vendorId: "vnd_4r349d2m72m7r2jx68z20tswx2",
description: "DeepL translation",
amount: 0.0052,
currency: "USD",
},
],
data: {
characters: 2600,
},
},
],
});
response = client.events.send_usage(
body={
"customer_id": "cust_47yxefzbfwkxragp01ccce965n",
"events": [
{
"id": "b1b2c3d4-0001-4000-8000-000000000001",
"event_type": "script_generated",
"occurred_at": "2026-05-28T11:50:00Z",
"subject": "video_gen_a7c23f91",
"description": "Script generation completed",
"costs": [
{
"id": "c1000000-0001-4000-8000-000000000001",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "GPT-4o script generation",
"amount": 0.0043,
"currency": "USD",
},
],
"data": {
"model": "gpt-4o",
"input_tokens": 512,
"output_tokens": 1840,
},
},
{
"id": "b1b2c3d4-0002-4000-8000-000000000002",
"event_type": "video_generated",
"occurred_at": "2026-05-28T11:51:48Z",
"subject": "video_gen_a7c23f91",
"description": "Video generation completed",
"costs": [
{
"id": "c1000000-0002-4000-8000-000000000002",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "Sora video generation (fast, 1080p)",
"amount": 0.32,
"currency": "USD",
},
],
"data": {
"model": "sora-fast",
"speed": "fast",
"minutes": 2,
},
},
{
"id": "b1b2c3d4-0003-4000-8000-000000000003",
"event_type": "subtitles_generated",
"occurred_at": "2026-05-28T11:53:12Z",
"subject": "video_gen_a7c23f91",
"description": "Subtitle generation completed",
"costs": [
{
"id": "c1000000-0003-4000-8000-000000000003",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "Whisper transcription",
"amount": 0.0048,
"currency": "USD",
},
],
"data": {
"model": "whisper-1",
"audio_minutes": 2,
},
},
{
"id": "b1b2c3d4-0004-4000-8000-000000000004",
"event_type": "translation_completed",
"occurred_at": "2026-05-28T11:54:51Z",
"subject": "video_gen_a7c23f91",
"description": "Subtitle translation completed",
"costs": [
{
"id": "c1000000-0004-4000-8000-000000000004",
"vendor_id": "vnd_4r349d2m72m7r2jx68z20tswx2",
"description": "DeepL translation",
"amount": 0.0052,
"currency": "USD",
},
],
"data": {
"characters": 2600,
},
},
],
},
)
All four events carry the same subject: "video_gen_a7c23f91". That's enough for Credyt to treat them as a single task, regardless of how far apart in time they arrive.
Listing tasks
The List Tasks endpoint returns a paged list of tasks, each with its aggregated profitability stats. This is the right starting point when you want to scan across many customers and jobs - for example, identifying tasks with low margins, or reviewing all the video jobs a specific customer has run this month.
GET https://api.credyt.ai/tasks
- REST API
- TypeScript SDK
- Python SDK
await client.tasks.list();
response = client.tasks.list()
The list can be sorted by last_updated_at, created_at, total_costs, gross_revenue, or margin, always in descending order. Sorting by total_costs or margin is particularly useful for cost audits - it surfaces your most expensive or least profitable jobs immediately.
Getting a task's details
The task detail endpoint returns the complete picture for a single task: every event in sequence, the aggregated stats, and a breakdown of costs by vendor.
GET https://api.credyt.ai/tasks/:taskId
- REST API
- TypeScript SDK
- Python SDK
Response
{
"id": "cust_47yxefzbfwkxragp01ccce965n:video_gen_a7c23f91",
"created_at": "2026-05-28T11:50:00Z",
"last_updated_at": "2026-05-28T11:54:51Z",
"customer": {
"id": "cust_47yxefzbfwkxragp01ccce965n",
"name": "Alex Rivera",
"external_id": "tasks_demo_001"
},
"stats": {
"gross_revenue": 0.56,
"total_costs": 0.3343,
"net_revenue": 0.2257,
"margin": 0.403,
"currency": "USD",
"event_count": 4
},
"events": [
{
"id": "b1b2c3d4-0001-4000-8000-000000000001",
"event_type": "script_generated",
"occurred_at": "2026-05-28T11:50:00Z",
"subject": "video_gen_a7c23f91",
"description": "Script generation completed",
"data": {
"model": "gpt-4o",
"input_tokens": 512,
"output_tokens": 1840
},
"customer_id": "cust_47yxefzbfwkxragp01ccce965n",
"created_at": "2026-05-28T12:01:34.943077Z",
"costs": [
{
"id": "c1000000-0001-4000-8000-000000000001",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "GPT-4o script generation",
"metadata": {},
"amount": 0.0043,
"currency": "USD"
}
],
"fees": [],
"stats": {
"gross_revenue": 0,
"total_costs": 0.0043,
"net_revenue": -0.0043,
"margin": -1,
"currency": "USD"
}
}
],
"vendors": [
{
"id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"name": "OpenAI",
"total_costs": 0.3291,
"currency": "USD"
},
{
"id": "vnd_4r349d2m72m7r2jx68z20tswx2",
"name": "DeepL",
"external_id": "deepl",
"total_costs": 0.0052,
"currency": "USD"
}
]
}
await client.tasks.get("cust_47yxefzbfwkxragp01ccce965n:video_gen_a7c23f91");
SDK response object
const response = {
id: "cust_47yxefzbfwkxragp01ccce965n:video_gen_a7c23f91",
createdAt: "2026-05-28T11:50:00Z",
lastUpdatedAt: "2026-05-28T11:54:51Z",
customer: {
id: "cust_47yxefzbfwkxragp01ccce965n",
name: "Alex Rivera",
externalId: "tasks_demo_001",
},
stats: {
grossRevenue: 0.56,
totalCosts: 0.3343,
netRevenue: 0.2257,
margin: 0.403,
currency: "USD",
eventCount: 4,
},
events: [
{
id: "b1b2c3d4-0001-4000-8000-000000000001",
eventType: "script_generated",
occurredAt: "2026-05-28T11:50:00Z",
subject: "video_gen_a7c23f91",
description: "Script generation completed",
data: {
model: "gpt-4o",
inputTokens: 512,
outputTokens: 1840,
},
customerId: "cust_47yxefzbfwkxragp01ccce965n",
createdAt: "2026-05-28T12:01:34.943077Z",
costs: [
{
id: "c1000000-0001-4000-8000-000000000001",
vendorId: "vnd_4c22r59kkbz0z2cnntdksn7t45",
description: "GPT-4o script generation",
metadata: {},
amount: 0.0043,
currency: "USD",
},
],
fees: [],
stats: {
grossRevenue: 0,
totalCosts: 0.0043,
netRevenue: -0.0043,
margin: -1,
currency: "USD",
},
},
],
vendors: [
{
id: "vnd_4c22r59kkbz0z2cnntdksn7t45",
name: "OpenAI",
totalCosts: 0.3291,
currency: "USD",
},
{
id: "vnd_4r349d2m72m7r2jx68z20tswx2",
name: "DeepL",
externalId: "deepl",
totalCosts: 0.0052,
currency: "USD",
},
],
};
response = client.tasks.get(
task_id="cust_47yxefzbfwkxragp01ccce965n:video_gen_a7c23f91",
)
SDK response object
response = {
"id": "cust_47yxefzbfwkxragp01ccce965n:video_gen_a7c23f91",
"created_at": "2026-05-28T11:50:00Z",
"last_updated_at": "2026-05-28T11:54:51Z",
"customer": {
"id": "cust_47yxefzbfwkxragp01ccce965n",
"name": "Alex Rivera",
"external_id": "tasks_demo_001",
},
"stats": {
"gross_revenue": 0.56,
"total_costs": 0.3343,
"net_revenue": 0.2257,
"margin": 0.403,
"currency": "USD",
"event_count": 4,
},
"events": [
{
"id": "b1b2c3d4-0001-4000-8000-000000000001",
"event_type": "script_generated",
"occurred_at": "2026-05-28T11:50:00Z",
"subject": "video_gen_a7c23f91",
"description": "Script generation completed",
"data": {
"model": "gpt-4o",
"input_tokens": 512,
"output_tokens": 1840,
},
"customer_id": "cust_47yxefzbfwkxragp01ccce965n",
"created_at": "2026-05-28T12:01:34.943077Z",
"costs": [
{
"id": "c1000000-0001-4000-8000-000000000001",
"vendor_id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"description": "GPT-4o script generation",
"metadata": {},
"amount": 0.0043,
"currency": "USD",
},
],
"fees": [],
"stats": {
"gross_revenue": 0,
"total_costs": 0.0043,
"net_revenue": -0.0043,
"margin": -1,
"currency": "USD",
},
},
],
"vendors": [
{
"id": "vnd_4c22r59kkbz0z2cnntdksn7t45",
"name": "OpenAI",
"total_costs": 0.3291,
"currency": "USD",
},
{
"id": "vnd_4r349d2m72m7r2jx68z20tswx2",
"name": "DeepL",
"external_id": "deepl",
"total_costs": 0.0052,
"currency": "USD",
},
],
}
The response shows the task clearly for what it is: a 2-minute video job that passed through four steps and two vendors, earned $0.56 in gross revenue, cost $0.33 to produce, and landed at a 40.3% margin. The script generation step contributed nothing to gross revenue - its cost is absorbed into the job's overall economics - while video rendering, subtitles, and translation all generated fees. The vendor breakdown confirms that OpenAI accounted for virtually all of the cost, with DeepL responsible for a small fraction.
What to look for
Tasks become most useful once you have volume. The patterns that tend to surface first:
Margin erosion at the step level - The per-event stats in the task detail show which steps consume the most cost relative to the revenue they earn. In the example above, the video_generated step runs at 20% margin, while subtitles_generated and translation_completed both run above 90%. The script_generated step returns margin: -1. If you're struggling with overall task profitability, the event breakdown tells you exactly where the pressure is.
Long-running or unexpectedly large tasks - Sorting the task list by total_costs descending shows you the most expensive jobs on your platform. A task accumulating far more events than typical - or costs far above your average - may indicate a runaway process, an unusually complex job, or a customer finding an unintended usage pattern.
Vendor concentration and cost distribution - The vendors array in the task detail shows which external services drive your cost structure. If a single vendor dominates costs across many tasks, that's both a business risk and a pricing signal. It may also point to optimisation opportunities - for example, routing simpler steps to a cheaper model.
Jobs that never resolve - Because a task has no explicit end state, a task that stopped accumulating events long ago but still shows no billing resolution may indicate a pipeline failure or an abandoned job. The gap between created_at and last_updated_at in the task list is a useful proxy for job duration.
Analysing tasks with the MCP server
Credyt's MCP server includes support for tasks, which makes it a natural fit for conversational cost analysis. Rather than writing queries or building dashboards, you can ask an AI assistant connected to your Credyt account to surface the information directly.
This is particularly useful when investigating a specific case. You can ask questions like "show me the most expensive video jobs this customer ran in May", "which tasks this week had a margin below 20%", or "pull up the full event breakdown for job video_gen_a7c23f91" and get a structured, readable answer in seconds. From there, you can drill in further - comparing that job to the customer's historical average, checking which vendor drove the cost spike, or looking at whether a similar pattern appears across other customers.
Compared to scripting API calls or exporting data, the MCP approach is better suited to exploratory work: the kind of investigation where you're not sure what you're looking for yet, and where the next question depends on what the previous answer shows.
Relationship to Profitability
Tasks are built on the same foundation as Credyt Profitability. The stats at the event level and the cost attribution model are identical. What tasks add is the aggregation layer: instead of reviewing events one by one, you get a single view that rolls up across the full lifecycle of a deliverable.
If you're already sending costs with your events and using the subject field consistently, Tasks require no additional integration. The data is already there.