Skip to integration docs

Documentation

Preview v0.1

TessaRun developer documentation

Learn how to authenticate, create generations, receive completion webhooks, manage Assets, handle billing, and use the API endpoints.

You bring

A funded Account, a Workspace key, and an application server.

Success means

You can submit a generation and retrieve its durable output Asset.

Base URL

https://api.tessarun.com/api/v1

01 · Concepts

Accounts, Workspaces, and tenants

TessaRun isolates infrastructure by Workspace. Your application still owns its users, authorization, workflow, and product-specific meaning.

Ownership map

One Account funds one or more isolated Workspaces.

AccountShared prepaid balance
control plane
Workspace A + key A

Owns its Generations, Assets, webhook endpoints, and usage.

Optional tenants inside Workspace A
customer-42

Its Generations, Assets, and usage

project-red

A different resource group

Workspace B + key B

Has its own resources and optional tenants. Its key receives 404 for Workspace A IDs.

TessaRun owns

Workspace isolation, durable operations and Assets, provider dispatch, signed webhook events, usage attribution, and prepaid charging.

Your application owns

Users, permissions, editorial state, workflow decisions, customer experience, and any billing of your downstream users.

A tenant groups related resources inside one Workspace.

A tenant is an optional identifier chosen by your application. It usually represents one of your customers, users, teams, or projects. For example, send "tenant": "customer-42" on that customer’s Generations and Assets. TessaRun returns the tenant on those resources, webhook events, and usage records, and list endpoints can filter by it.

Use tenant to group many resources. Use metadata to attach your own user, project, organization, or other identifiers to a resource. The Workspace API key still controls access; neither tenant nor metadata grants permission.

02 · Quickstart

Create your first generation

Create and fund an Account, create a Workspace key, then run these requests from your server. The plaintext key is shown once.

  1. 01List modelsGET /models
  2. 02Choose a preview modelGET /models/:model_id
  3. 03Create a generationPOST /generations

Step 1 · Request

List available models

curl · list models
curl https://api.tessarun.com/api/v1/models \
  -H "Authorization: Bearer $TESSARUN_API_KEY"

Step 1 · 200 OK · selected fields

Choose an available model

{
  "object": "list",
  "data": [{
    "id": "krea-2",
    "name": "KREA 2",
    "type": "image",
    "capabilities": ["text_to_image"],
    "availability": "preview",
    "parameters": {
      "prompt": {"type": "string", "required": true},
      "aspect_ratio": {"type": "enum", "default": "4:5"},
      "resolution": {"type": "enum", "default": "1.5k"}
    }
  }]
}
Use a model whose availability is preview.

The model list can include models that are visible but do not accept generation requests yet. Read GET /models/krea-2 for the complete parameter schema before building the request body.

Step 3 · Request

Create a generation request

curl · create generation
curl https://api.tessarun.com/api/v1/generations \
  -H "Authorization: Bearer $TESSARUN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "krea-2",
    "tenant": "customer-42",
    "params": {
      "prompt": "A copper robot in a daylight studio",
      "aspect_ratio": "4:5",
      "resolution": "1.5k"
    },
    "metadata": {
      "user_id": "user-42",
      "project_id": "project-7",
      "org_id": "org-3"
    }
  }'

Immediate response · 202 Accepted · selected fields

Handle the 202 response

{
  "id": "0190d9b8-7d31-7c0b-9aaa-4a0d0d2466ad",
  "object": "generation",
  "status": "pending",
  "model": "krea-2",
  "tenant": "customer-42",
  "metadata": {
    "user_id": "user-42",
    "project_id": "project-7",
    "org_id": "org-3"
  },
  "price": {"amount": 7, "currency": "usd", "unit": "cent"},
  "assets": [],
  "error": null,
  "accepted_at": "2026-08-17T18:42:05Z",
  "created_at": "2026-08-17T18:42:05Z"
}

Terminal response · 200 OK · selected fields

Download the output Asset

{
  "id": "0190d9b8-7d31-7c0b-9aaa-4a0d0d2466ad",
  "object": "generation",
  "status": "succeeded",
  "model": "krea-2",
  "price": {"amount": 7, "currency": "usd", "unit": "cent"},
  "assets": [{
    "id": "0190d9c1-46ba-78be-8123-6d40462e26bd",
    "object": "asset",
    "status": "ready",
    "media_kind": "image",
    "mime_type": "image/png"
  }],
  "error": null,
  "finished_at": "2026-08-17T18:42:41Z"
}

Status check

GET /generations/0190d9b8-...

After a completion webhook, read the generation to retrieve its full Asset or error details.

Download

GET /assets/0190d9c1-.../download

The response contains a short-lived download URL. Treat that URL as a secret capability.

03 · Request fields

Identifiers and request metadata

Authentication, attribution, and application metadata serve different purposes.

Value Job Scope Do not use it for
Workspace key Authentication and resource isolation One Workspace A downstream browser or mobile session
tenant Groups many resources for one customer, user, team, or project Reusable inside one Workspace Authorization, authentication, or a separate balance
metadata Your identifiers and other structured context, returned unchanged Stored on a resource Indexed lookup, trust decisions, or billing

tenant accepts at most 255 characters. metadata must be a JSON object and accepts at most 32,000 encoded bytes per resource.

04 · Generations

Generation lifecycle

A generation moves forward through managed work. Your request connection may end; the generation continues until a terminal state.

1pendingAccepted, priced, debited, queued
2submittedProvider accepted dispatch
3runningProvider reports active work
succeededOutput Asset + usage record
failedError + full refund
Acceptance

Validation, price fixation, operation creation, debit, and accepted event commit together.

Success

TessaRun materializes output as a durable ready Asset and records successful usage.

Failure

TessaRun records a stable error and fully refunds the accepted charge.

05 · Assets

Media inputs and Asset uploads

A URL is read for one generation. An Asset is a durable, Workspace-scoped media resource that can be reused and downloaded later.

Use asset_id when

  • The input should remain durable.
  • You will reuse or audit it.
  • You want Workspace ownership checked.
"image": {"asset_id": "0190..."}

Use url when

  • The HTTPS source is temporary.
  • It stays readable until dispatch begins.
  • You do not need a TessaRun Asset for the input.
"image": {"url": "https://..."}

Direct upload sequence

  1. 01 · CreatePOST /assets

    Receive the pending Asset and short-lived PUT URL.

  2. 02 · UploadPUT signed_url

    Upload bytes directly to object storage.

  3. 03 · CompletePOST /assets/:id/complete

    TessaRun verifies the object and marks it ready.

  4. 04 · Useasset_id or /download

    Reference it in work or request a short-lived GET URL.

Ready means usable.

A generation input must reference a ready Asset of the correct media kind in the same Workspace. A temporary URL input does not create an Asset. Keep upload and download URLs out of logs because possession grants temporary access.

06 · Webhooks

Generation webhooks

Register an HTTPS endpoint and select the generation event types your application needs. TessaRun sends each selected event to that endpoint.

Register an endpoint

Choose event types

curl https://api.tessarun.com/api/v1/webhook_endpoints \
  -H "Authorization: Bearer $TESSARUN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://app.example.com/webhooks/tessarun",
    "event_types": [
      "generation.succeeded",
      "generation.failed"
    ]
  }'

201 Created · selected fields

Store the signing secret

{
  "id": "0190da31-75b6-742d-93eb-4907d32d2c15",
  "object": "webhook_endpoint",
  "url": "https://app.example.com/webhooks/tessarun",
  "event_types": [
    "generation.failed",
    "generation.succeeded"
  ],
  "status": "active",
  "signing_secret": "whsec_..."
}

The signing secret is returned only when the endpoint is created or its secret is rotated. An empty event_types array subscribes the endpoint to every available type.

Verify every delivery

  1. 1. Read the exact raw request body.
  2. 2. Reject webhook-timestamp values more than five minutes from the current time.
  3. 3. Compare the HMAC signature in constant time before decoding JSON.
  4. 4. Return a 2xx response after accepting the event.

Signed HTTP POST

Webhook delivery

{
  "id": "0190da43-ddc4-79f5-b78e-e011866a78cc",
  "object": "event",
  "type": "generation.succeeded",
  "operation_id": "0190d9b8-7d31-7c0b-9aaa-4a0d0d2466ad",
  "tenant": "customer-42",
  "data": {
    "id": "0190d9b8-7d31-7c0b-9aaa-4a0d0d2466ad",
    "status": "succeeded",
    "model": "krea-2",
    "price_cents": 7
  },
  "metadata": {
    "user_id": "user-42",
    "project_id": "project-7",
    "org_id": "org-3"
  },
  "occurred_at": "2026-08-17T18:42:41Z"
}
Signature input

Deliveries include webhook-id, webhook-timestamp, and webhook-signature. The signed content is webhook-id.webhook-timestamp.raw_body using HMAC-SHA256 and the endpoint secret. After a terminal event, use GET /generations/:generation_id once to retrieve the complete output Assets or failure details.

07 · Billing

Pricing, balances, and refunds

The parent Account holds the prepaid balance shared by its Workspaces. A Workspace key can read only that Workspace’s resources, successful usage, and attributed ledger entries.

When accepted

Fixed price is charged

TessaRun charges the price returned with the accepted generation response.

If the generation succeeds

Charge remains; usage is recorded

Successful work appears in /usage with tenant and metadata attribution.

If the generation fails

Charge is fully refunded

Failed work does not create a successful usage record.

GET /usage

Returns the current shared Account prepaid balance plus successful usage attributed to this Workspace.

GET /balance_transactions

Returns immutable charges and refunds attributed to this Workspace. Account funding and sibling Workspace entries stay excluded.

08 · Errors

Error handling

Error bodies use error.type, an optional human message, and optional details. Provider and database internals do not cross the public boundary.

{
  "error": {
    "type": "validation_error",
    "details": [{
      "field": "prompt",
      "message": "must be at most 20000 encoded bytes"
    }]
  }
}
Status Typical meaning Your action
401 Missing, invalid, expired, inactive, or blocked key Stop and repair credentials or Account state.
402 Insufficient funds or past-due Account Add funds, then submit the work.
404 Unknown ID or ID owned by another Workspace Check the ID and authenticated Workspace.
422 Validation, model, or media-input error Correct the request before submitting a new generation.

Use the HTTP status and error.type for program logic. Use the OpenAPI document for the wire-level response schema.

09 · Reference

API endpoints

This endpoint index belongs to the workflow explained above. The OpenAPI 3.1 document remains the canonical source for request and response schemas.

Models

GET
/models

List discoverable logical models.

GET
/models/{model_id}

Read one model and its current parameter schema.

Generations

GET
/generations

List recent Workspace generations.

POST
/generations

Validate, price, debit, and submit managed work.

GET
/generations/{generation_id}

Read current state, price, errors, and output Assets.

Assets

GET
/assets

List durable Workspace Assets.

POST
/assets

Create a pending Asset and direct upload request.

GET
/assets/{asset_id}

Read one Asset in the authenticated Workspace.

POST
/assets/{asset_id}/complete

Verify the stored object and mark the Asset ready.

GET
/assets/{asset_id}/download

Create a short-lived direct download URL.

Webhooks, usage, and balance

GET
/webhook_event_types

List the available webhook event types.

GET
/webhook_endpoints

List Workspace webhook endpoints.

POST
/webhook_endpoints

Register an HTTPS destination and receive its signing secret.

GET
/webhook_endpoints/{webhook_endpoint_id}

Read one Workspace webhook endpoint.

PATCH
/webhook_endpoints/{webhook_endpoint_id}

Change the URL, event selection, description, or status.

DELETE
/webhook_endpoints/{webhook_endpoint_id}

Delete a webhook endpoint.

POST
/webhook_endpoints/{webhook_endpoint_id}/rotate_secret

Replace the endpoint signing secret.

GET
/usage

Read successful usage and the shared prepaid balance.

GET
/balance_transactions

List Workspace-attributed charges and refunds.

10 · Operations

Best practices

Follow these practices when storing credentials, handling webhook events and media, and reconciling usage.

  • Keep Workspace keys on the server and out of client bundles, logs, and transcripts.

  • Separate environments with separate Workspaces when independent isolation is useful.

  • Persist every returned generation ID beside your own job or resource record.

  • Subscribe to generation.succeeded and generation.failed, then handle both.

  • Verify webhook timestamps and signatures against the exact raw request body.

  • Use ready Assets for durable or reusable media; keep signed URLs out of logs.

  • Authorize downstream users in your application; use tenant only for attribution.

  • Handle 401, 402, 404, and 422 responses explicitly.

  • Monitor prepaid balance and reconcile usage and ledger entries by Workspace.

  • Pin integration tests to OpenAPI and the exact endpoint behavior you depend on.