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

# Upload Delegation

> Generate secure tokens for merchant file uploads

## Overview

The delegate-upload endpoint allows your Platform to generate secure, short-lived JWT tokens for your merchants' frontend upload widgets (Uppy). This enables direct browser-to-storage uploads while maintaining proper attribution and billing.

<Info>
  Delegated tokens expire after **5 minutes** by default. Request a fresh token for each upload session.
</Info>

## Endpoint

```http theme={"theme":"github-dark"}
POST /v1/auth/delegate-upload
```

## Authentication

This endpoint requires your Platform API key in the Authorization header:

```http theme={"theme":"github-dark"}
Authorization: Bearer your_platform_api_key
```

<Warning>
  Never expose your Platform API key in frontend code. The delegate-upload call must be made from your backend.
</Warning>

## Request Body

| Field         | Type   | Required | Description                               |
| ------------- | ------ | -------- | ----------------------------------------- |
| `merchant_id` | string | Yes      | Your internal identifier for the merchant |

### Example Request

<CodeGroup>
  ```bash cURL theme={"theme":"github-dark"}
  curl -X POST https://api.superseeded.ai/v1/auth/delegate-upload \
    -H "Authorization: Bearer your_platform_api_key" \
    -H "Content-Type: application/json" \
    -d '{"merchant_id": "merchant_123"}'
  ```

  ```python Python theme={"theme":"github-dark"}
  import requests

  response = requests.post(
      "https://api.superseeded.ai/v1/auth/delegate-upload",
      headers={"Authorization": "Bearer your_platform_api_key"},
      json={"merchant_id": "merchant_123"}
  )
  token_data = response.json()
  ```

  ```javascript Node.js theme={"theme":"github-dark"}
  const response = await fetch('https://api.superseeded.ai/v1/auth/delegate-upload', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer your_platform_api_key',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({ merchant_id: 'merchant_123' })
  });
  const tokenData = await response.json();
  ```
</CodeGroup>

## Response

<ResponseField name="token" type="string" required>
  Short-lived JWT token for Uppy authentication
</ResponseField>

<ResponseField name="expires_at" type="string" required>
  ISO 8601 timestamp when the token expires
</ResponseField>

### Example Response

```json theme={"theme":"github-dark"}
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_at": "2024-01-20T12:05:00Z"
}
```

## JWT Token Claims

The generated token contains claims that are used for attribution and billing:

| Claim         | Description                        |
| ------------- | ---------------------------------- |
| `sub`         | The merchant\_id you provided      |
| `api_key_id`  | Your Platform's API key identifier |
| `scope`       | Token scope (e.g., `upload`)       |
| `entity_type` | Entity type identifier             |
| `exp`         | Token expiration timestamp         |
| `iat`         | Token issued-at timestamp          |

<Info>
  The same delegation token is used for both the TUS upload **and** the subsequent processing request. This simplifies your integration since one token handles the entire flow.
</Info>

## Usage Flow

<Steps>
  <Step title="Merchant Initiates Upload">
    Your merchant clicks an upload button in your frontend application.
  </Step>

  <Step title="Request Delegation Token">
    Your backend calls the `delegate-upload` endpoint with the merchant's ID.

    ```javascript theme={"theme":"github-dark"}
    // Your backend
    const { token, expires_at } = await getDelegationToken(merchantId);
    ```
  </Step>

  <Step title="Pass Token to Frontend">
    Send the JWT token to your frontend Uppy widget.

    ```javascript theme={"theme":"github-dark"}
    // Return to frontend
    res.json({ uploadToken: token });
    ```
  </Step>

  <Step title="Configure Uppy">
    Your frontend configures Uppy with the delegation token.

    ```javascript theme={"theme":"github-dark"}
    const uppy = new Uppy()
      .use(Tus, {
        endpoint: 'https://tus.superseeded.com/files/',
        headers: {
          Authorization: `Bearer ${uploadToken}`
        }
      });
    ```
  </Step>

  <Step title="Direct Upload">
    Uppy uploads the file directly to our TUS server using the token for authentication. After the upload completes, Uppy returns the file URL.
  </Step>

  <Step title="Call Processing Endpoint">
    Your frontend calls the verify-pot-sizes endpoint with the **same delegation token** and the uploaded file URL.

    ```javascript theme={"theme":"github-dark"}
    const response = await fetch('https://api.superseeded.ai/v1/verify/pot-sizes', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${uploadToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        file_url: uploadResult.uploadURL
      })
    });
    const { results } = await response.json();
    ```
  </Step>

  <Step title="Receive Enriched Data">
    The API fetches the file internally, processes it, bills the merchant (from the JWT), and returns enriched data directly in the response. See [Verify Pot Sizes from Upload](/platform-integration/tus-webhook) for the full response schema.
  </Step>
</Steps>

## Error Responses

| Status | Error             | Description                           |
| ------ | ----------------- | ------------------------------------- |
| `401`  | `unauthorized`    | Invalid or missing API key            |
| `400`  | `invalid_request` | Missing `merchant_id` in request body |
| `429`  | `rate_limited`    | Too many token requests               |

## Best Practices

<AccordionGroup>
  <Accordion title="Request tokens just-in-time">
    Don't pre-fetch tokens. Request a fresh token when the user is ready to upload to ensure it doesn't expire mid-upload.
  </Accordion>

  <Accordion title="Handle token expiration">
    If an upload fails due to token expiration, request a new token and retry. Uppy supports automatic retry with updated headers.
  </Accordion>

  <Accordion title="Use consistent merchant IDs">
    Use your internal user/merchant ID consistently. This ID is used for billing aggregation and usage tracking.
  </Accordion>
</AccordionGroup>
