# Reslide API guide

Reslide by Tosea converts existing PDF pages or slide images into editable PowerPoint (`.pptx`) files. The service reconstructs visible page content as PowerPoint objects where applicable; it does not recover hidden authoring data that is absent from a flattened input.

- Product site: `https://pptx.tosea.ai`
- API base: `https://pptx-api.tosea.ai`
- Interactive reference: `https://pptx.tosea.ai/docs`
- OpenAPI 3.1: `https://pptx-api.tosea.ai/openapi.json`
- API keys: `https://pptx.tosea.ai/keys`
- Support: `support@tosea.ai`

This guide was checked against the public route implementation on 2026-07-30. The live OpenAPI document and authenticated `GET /v1/limits` response are the sources of truth for the deployed contract.

## Authentication

Create an API key after signing in at `/keys`. A key starts with `tpx_live_` and is shown in full only when it is created. Store it in a secret manager and send it as a Bearer token:

```http
Authorization: Bearer tpx_live_...
```

Never put an API key in frontend JavaScript, a public repository, a URL, an AI prompt, or this documentation. Examples below read it from `TOSEA_PPTX_API_KEY`.

## Response envelope

Every documented REST response uses the same JSON envelope:

```json
{
  "code": 0,
  "message": "ok",
  "data": {}
}
```

`code == 0` means success. Otherwise, `code` mirrors the HTTP status. `message` is for humans and is not a stable value to parse.

## Inputs and operations

Create a task with exactly one input form:

| Operation | Input field | Use |
| --- | --- | --- |
| `pdf_to_pptx` | `upload_id` | A local/private PDF first sent to `POST /v1/uploads` |
| `pdf_to_pptx` | `pdf_url` | A publicly retrievable PDF hosted by your system |
| `images_to_pptx` | `upload_ids` | Local/private page images uploaded individually, in slide order |
| `images_to_pptx` | `image_urls` | Public PNG, JPG/JPEG, or WebP page-image URLs, in slide order |

The upload endpoint accepts PDF, PNG, JPG/JPEG, and WebP. Each image represents one slide. For PDF tasks, optional `input.pages` contains 1-based page numbers; omit it to convert every page.

An optional `input.title` can be up to 200 characters. An optional top-level HTTPS `callback_url` receives a signed terminal-state webhook.

## Quick start with a public PDF

```bash
curl -X POST https://pptx-api.tosea.ai/v1/tasks \
  -H "Authorization: Bearer $TOSEA_PPTX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-2026-001" \
  -d '{
    "operation": "pdf_to_pptx",
    "input": {
      "pdf_url": "https://example.com/deck.pdf",
      "pages": [1, 2, 5],
      "title": "Editable review deck"
    },
    "callback_url": "https://example.com/webhooks/reslide"
  }'
```

Keep the returned `data.task_id`. The idempotency key should identify the conversion in your own system. Retrying the create request with the same key returns the existing task instead of charging again.

## Quick start with a local PDF

Upload the file:

```bash
curl -X POST https://pptx-api.tosea.ai/v1/uploads \
  -H "Authorization: Bearer $TOSEA_PPTX_API_KEY" \
  -F "file=@deck.pdf"
```

Then create the task with the returned upload ID:

```bash
curl -X POST https://pptx-api.tosea.ai/v1/tasks \
  -H "Authorization: Bearer $TOSEA_PPTX_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: local-deck-2026-001" \
  -d '{
    "operation": "pdf_to_pptx",
    "input": {
      "upload_id": "UPLOAD_UUID_HERE",
      "title": "Local PDF conversion"
    }
  }'
```

Upload records and their API access expire after 24 hours. This is an access-lifetime statement, not a promise that the underlying storage object is physically deleted at that exact time. Image-upload responses also include a signed `preview_url`; PDFs do not.

## Quick start with local page images

Upload each PNG, JPG/JPEG, or WebP separately. Preserve slide order when collecting the returned IDs:

```json
{
  "operation": "images_to_pptx",
  "input": {
    "upload_ids": [
      "UPLOAD_UUID_FOR_SLIDE_1",
      "UPLOAD_UUID_FOR_SLIDE_2"
    ],
    "title": "Image sequence"
  }
}
```

One image is one page and one credit on success.

## Polling and download

```bash
curl https://pptx-api.tosea.ai/v1/tasks/TASK_UUID_HERE \
  -H "Authorization: Bearer $TOSEA_PPTX_API_KEY"
```

Task states are `pending`, `processing`, `succeeded`, `failed`, and `canceled`. Poll every few seconds, or use a callback. On success, `data.result.pptx_url` is a signed download URL valid for 24 hours. Download it promptly and store the file in your own system.

Failed or canceled tasks have zero net billable task credits. Their reservations are reconciled against the original paid and bonus pools under those pools' lifecycle rules; this does not promise that a later credit batch or visible balance will increase.

## Public REST endpoints

All routes below require a Bearer API key.

| Method | Route | Purpose |
| --- | --- | --- |
| `POST` | `/v1/uploads` | Upload one temporary PDF or page image |
| `POST` | `/v1/tasks` | Create a PDF or image-list conversion task |
| `GET` | `/v1/tasks/{task_id}` | Read status and the successful result URL |
| `GET` | `/v1/tasks` | List tasks newest first with cursor pagination |
| `POST` | `/v1/tasks/{task_id}/cancel` | Cancel a non-terminal task; it will have zero net billable task credits |
| `GET` | `/v1/credits` | Read paid, bonus, and combined balances |
| `GET` | `/v1/usage` | Read paginated credit-ledger history |
| `GET` | `/v1/limits` | Read effective task, upload, concurrency, and per-page limits |

The task list accepts optional `operation`, comma-separated `status`, `limit` (1–100), and `after` cursor parameters. The usage route accepts 1-based `page` and `page_size` (1–100).

## Billing and current public plans

- 1 credit = 1 selected PDF page or 1 source image.
- Credits are reserved when a task is created.
- The reservation settles when the task succeeds.
- Failed and canceled tasks have zero net billable task credits; reservations are reconciled against their original pools subject to those pools' lifecycle rules.
- The web workspace and API share one account balance.
- Paid subscription credits are valid in their billing window and do not roll over. Bonus credits are tracked separately and do not expire under the current public API contract.

Current published monthly tiers:

| Plan | Published price | Page allowance | Concurrent tasks |
| --- | ---: | ---: | ---: |
| Free | $0 | 10 pages, one-time | 1 |
| Starter | $19/month | 300 pages/month | 2 |
| Pro | $49/month | 1,000 pages/month | 4 |
| Ultra | $149/month | 4,000 pages/month | 8 |

The site also publishes a yearly billing option at a 40% discount, billed yearly, with credits issued in monthly windows. Pricing and plan policy can change; verify the homepage pricing section and your billing screen before presenting a quote.

The current deployment defaults are 100 pages per task and 100MB per upload. Use `GET /v1/limits` to read effective values for your account and deployment.

## Rate limits and errors

The current per-key implementation uses 10 requests per second with a burst of 30. Plan concurrency can also cause a `429`. Always honor `Retry-After`, use exponential backoff for retryable server errors, and avoid creating duplicate tasks.

Common statuses:

| Status | Meaning | Integration response |
| --- | --- | --- |
| `400` | Invalid request or unsupported input | Correct the request; do not retry unchanged |
| `401` | Missing, malformed, revoked, or invalid API key | Fix or rotate the key |
| `402` | Insufficient credits | Check `/v1/credits` and billing |
| `404` | Task or resource not available to this account | Check the ID and ownership |
| `409` | State conflict | Refresh task state before deciding what to do |
| `429` | Rate or concurrency limited | Wait for `Retry-After` and retry safely |
| `5xx` | Server-side failure | Retry once with backoff and the same idempotency key |

## Webhooks

Provide an HTTPS `callback_url` on task creation. Reslide sends a `task.finished` payload when the task reaches `succeeded`, `failed`, or `canceled`.

- Delivery is at least once with exponential-backoff retries for about a day.
- Return any 2xx within 15 seconds.
- Deduplicate side effects by `task_id`.
- Polling the task endpoint remains the fallback.
- Read the webhook secret from `/keys`; do not confuse it with the API key.

Every delivery includes:

```http
X-Tosea-Signature: sha256=HEX_DIGEST
```

The digest is HMAC-SHA256 of the raw request body keyed by your webhook secret:

```python
import hashlib
import hmac

def verify(secret: str, raw_body: bytes, signature_header: str) -> bool:
    digest = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(f"sha256={digest}", signature_header)
```

Verify the raw bytes before parsing JSON. Do not log the secret or the full signed result URL.

## Editing expectations and source limitations

The service is designed to reconstruct visible page regions as editable PowerPoint content such as text boxes, shapes, and separate pictures. It is not a bit-for-bit recovery of the original authoring file.

Review at least:

- small text, numbers, proper nouns, and line breaks;
- fonts that may not exist in the viewing environment;
- charts, formulas, dense tables, and detailed diagrams;
- transparency, blur, shadows, gradients, and overlapping content;
- reading order, cropping, and slide aspect ratio;
- rights to reproduce source imagery and copy.

A flattened PDF or image does not contain hidden notes, links, videos, animations, transitions, prompt history, source data, original design layers, or off-canvas objects. The API does not fact-check or verify citations.

## Machine and agent resources

- Concise model index: `https://pptx.tosea.ai/llms.txt`
- Extended model context: `https://pptx.tosea.ai/llms-full.txt`
- Agent workflow: `https://pptx.tosea.ai/skills/pptx-convert/SKILL.md`
- OpenAPI: `https://pptx-api.tosea.ai/openapi.json`

The agent workflow never requires a user to paste a secret into a conversation. Set `TOSEA_PPTX_API_KEY` in the execution environment and keep all network and file actions within the scope the user authorized.
