> ## Documentation Index
> Fetch the complete documentation index at: https://docs.robinzip.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart

> Compress a podcast episode from upload to download in five steps

This walkthrough uploads an MP3, processes it with the `podcast` preset, and downloads the compressed `.ogg` result. All you need is `curl`.

<Steps>
  <Step title="Create an API key">
    Create a key in the dashboard under **Settings → API Keys**. The full key (`sk_live_...`) is shown once; copy it immediately, since only a hash is stored.

    ```bash theme={null}
    export ROBIN_KEY="sk_live_..."
    ```
  </Step>

  <Step title="Request an upload URL">
    Declare the filename and size in bytes. You get back a presigned URL valid for 15 minutes.

    ```bash theme={null}
    curl -s https://api.robinzip.app/v1/upload \
      -H "Authorization: Bearer $ROBIN_KEY" \
      -H "Content-Type: application/json" \
      -d '{"filename": "episode.mp3", "size": 52428800}'
    ```

    ```json theme={null}
    {
      "success": true,
      "data": {
        "id": "665f1c2ab8d4e91a2c3d4e5f",
        "uploadUrl": "https://...signed-put-url...",
        "contentType": "audio/mpeg",
        "uploadUrlExpiresIn": 900,
        "expiresAt": "2026-07-12T14:00:00.000Z"
      }
    }
    ```
  </Step>

  <Step title="PUT the file to the upload URL">
    Use exactly the `contentType` returned in the previous step: the signature is bound to it.

    ```bash theme={null}
    curl -s -X PUT "$UPLOAD_URL" \
      -H "Content-Type: audio/mpeg" \
      --data-binary @episode.mp3
    ```
  </Step>

  <Step title="Create the audio job">
    Reference the upload `id` as `audioId` and pick the `podcast` preset.

    ```bash theme={null}
    curl -s https://api.robinzip.app/v1/audio \
      -H "Authorization: Bearer $ROBIN_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: episode-42" \
      -d '{"audioId": "665f1c2ab8d4e91a2c3d4e5f", "preset": "podcast"}'
    ```

    ```json 202 Accepted theme={null}
    {
      "success": true,
      "data": {
        "id": "665f1d00b8d4e91a2c3d4e60",
        "status": "created"
      }
    }
    ```

    Credits are reserved now, based on file size (1 credit per started 5 MB for audio). They are refunded automatically if the job fails.
  </Step>

  <Step title="Wait for the job and download the result">
    Pass `?wait=25` to long-poll: the server holds the response until the job finishes (or 25 seconds pass), so you usually need a single call instead of a polling loop.

    ```bash theme={null}
    curl -s "https://api.robinzip.app/v1/jobs/665f1d00b8d4e91a2c3d4e60?wait=25" \
      -H "Authorization: Bearer $ROBIN_KEY"
    ```

    If the job is still running when the wait expires, just repeat the call. When it's `completed`:

    ```json theme={null}
    {
      "success": true,
      "data": {
        "id": "665f1d00b8d4e91a2c3d4e60",
        "status": "completed",
        "result": {
          "outputUrl": "https://...signed-get-url...",
          "metrics": {
            "inputSize": 52428800,
            "outputSize": 6291456,
            "compressionRatio": 8.33,
            "operationsApplied": ["trim-silence", "normalize", "compress", "encode"]
          }
        }
      }
    }
    ```

    Download the Opus-encoded output:

    ```bash theme={null}
    curl -s -o episode.ogg "$OUTPUT_URL"
    ```

    `outputUrl` is a fresh signed URL on every read, valid for 1 hour. Results stay available for 7 days after completion.
  </Step>
</Steps>

Prefer a push model over polling? Add a `webhookUrl` to the job body; see [Webhooks](/concepts/webhooks).
