# Make API requests
Learn how to work with Mux's API through HTTP requests.
## HTTP basic auth

| Term         | Description                                            |
| :----------- | :----------------------------------------------------- |
| Token ID     | access token ID, the "username" in HTTP basic auth     |
| Token secret | access token secret, the "password" in HTTP basic auth |

Every request to the API is authenticated via an [Access Token](https://dashboard.mux.com/settings/access-tokens), which includes the ID and the secret key. You can think of the Access Token’s ID as its username and secret as the password. Mux only stores a hash of the secret, not the secret itself. If you lose the secret key for your access token, Mux cannot recover it; you will have to create a new Access Token. If the secret key for an Access Token is leaked you should revoke that Access Token on the settings page: https://dashboard.mux.com/settings/access-tokens.

Note that in order to access the settings page for access tokens you must be an admin on the Mux organization.

API requests are authenticated via HTTP Basic Auth, where the username is the Access Token ID, and the password is the Access Token secret key. Due to the use of Basic Authentication and because doing so is just a Really Good Idea™, all API requests must made via HTTPS (to `https://api.mux.com`).

<Callout type="warning" title="Watch out for mismatched tokens and environments">
  Access tokens are scoped to an environment, for example: a development token cannot be used in requests to production. Verify the intended environment when creating an access token.
</Callout>

This is an example of authenticating a request with cURL, which automatically handles HTTP Basic Auth. If you run this request yourself it will not work, you should replace the Access Token ID (`44c819de-4add-4c9f-b2e9-384a0a71bede`) and secret (`INKxCoZ+cX6l1yrR6vqzYHVaeFEcqvZShznWM1U/No8KsV7h6Jxu1XXuTUQ91sdiGONK3H7NE7H`) in this example with your own credentials.

```shell
curl https://api.mux.com/video/v1/assets \
  -H "Content-Type: application/json" \
  -X POST \
  -d '{ "inputs": [{ "url": "https://muxed.s3.amazonaws.com/leds.mp4" }], "playback_policies": ["public"], "video_quality": "basic" }' \
  -u 44c819de-4add-4c9f-b2e9-384a0a71bede:INKxCoZ+cX6l1yrR6vqzYHVaeFEcqvZShznWM1U/No8KsV7h6Jxu1XXuTUQ91sdiGONK3H7NE7H
```

HTTP basic auth works by base64 encoding the username and password in an `Authorization` header on the request.

Specifically, the header looks something like this:

```bash
'Authorization': 'Basic base64(MUX_TOKEN_ID:MUX_TOKEN_SECRET)'
```

1. The access token ID and secret are concatenated with a `:` and the string is base64 encoded.
2. The value for the `Authorization` header is the string `Basic` plus a space ` ` followed by the base64 encoded result from Step 1.

In the cURL example above, the cURL library is taking care of the base64 encoding and setting the header value internally. The HTTP library you use in your server-side language will probably have something similar for handling basic auth. You should be able to pass in the `username` (Access Token ID) and `password` (Access Token secret) and the library will handle the details of formatting the header.

## Access token permissions

<Callout type="success" title="Full Permissions">
  If you're just getting started with Mux Video, use Read and Write.
</Callout>

If you are creating or modifying resources with Mux Video then you need **Read** and **Write** permissions. This includes things like:

* Creating new assets
* Creating direct uploads
* Creating new live streams

If you need to create signed tokens for secure video playback, your access token needs **System** write permissions. Learn more about [secure video playback](/docs/guides/secure-video-playback) and <ApiRefLink href="/docs/api-reference/system/signing-keys">signing keys</ApiRefLink>.

Mux Data only requires **Write** permissions if you need to create Annotations via API. Annotations created in the Dashboard do not require **Write** permissions.

<Image src="/docs/images/new-access-token.png" width={760} height={376} alt="Mux access token permissions" sm />

If your code is not creating anything and only doing `GET` requests then you can restrict the access token to **Read** only.

## CORS and client side API requests

Mux API endpoints do not have CORS headers, which means if you try to call the Mux API from the browser you will get an error:

<Callout type="error" title="CORS Error in Browser">
  request has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
</Callout>

This is expected. Although making API requests directly from the browser or your mobile app would be convenient, it leaves a massive security hole in your application by the fact that your client side code would contain your API keys. Anyone who accesses your application would have the ability to steal your API credentials and make requests to Mux on your behalf. An attacker would be able to gain full control of your Mux account.

Mux API Credentials should never be stored in a client application. All Mux API calls should be made from a trusted server.

Instead of trying to make API requests from the client, the flow that your application should follow is:

1. Client makes a request to your server
2. Your server makes an authenticated API request to Mux
3. Your server saves whatever it needs in your database
4. Your server responds to the client with only the information that the client needs. For example, with live streaming that's the stream key for a specific stream, for uploads that's just the direct upload URL

## Using Mux with serverless functions

Serverless functions are a great way to add pieces of secure server-side code to your client heavy application. Examples of services that help you run serverless functions are:

* [AWS Lambda](https://aws.amazon.com/lambda/)
* [Firebase Cloud Functions](https://firebase.google.com/docs/functions)
* [Cloudflare Workers](https://workers.cloudflare.com/)
* [Vercel Functions](https://vercel.com/docs/functions)
* [Netlify Functions](https://docs.netlify.com/functions/overview/)

The basic idea behind serverless functions is that you can write a bit of server code and deploy it to run on these platforms. Your client application can make requests to these endpoints to perform specific actions. Below is an example from [with-mux-video](https://github.com/vercel/next.js/blob/canary/examples/with-mux-video/pages/api/upload.js) of a serverless function endpoint that makes an API call to create a Mux Direct Upload.

```js
// pages/api/upload.js
// see: https://github.com/vercel/next.js/tree/canary/examples/with-mux-video
import Mux from '@mux/mux-node';

const mux = new Mux();

export default async function uploadHandler(req, res) {
  const { method } = req;

  switch (method) {
    case 'POST':
      try {
        const upload = await mux.video.uploads.create({
          new_asset_settings: { playback_policy: ['public'], video_quality: 'basic' },
          cors_origin: '*',
        });
        res.json({
          id: upload.id,
          url: upload.url,
        });
      } catch (e) {
        console.error('Request error', e);
        res.status(500).json({ error: 'Error creating upload' });
      }
      break;
    default:
      res.setHeader('Allow', ['POST']);
      res.status(405).end(`Method ${method} Not Allowed`);
  }
}
```

## API pagination

Our list endpoints (such as <ApiRefLink href="/docs/api-reference/video/assets/list-assets">List Assets</ApiRefLink>) do not return every single relevant record.
To offer everyone the best performance we limit the amount of records you can receive and offer pagination parameters to help you navigate through your list.

### Page/limit pagination

Our most common pagination controls are `page` and `limit`.

| Parameter | Default | Maximum | Description                                      |
| :-------- | :------ | :---- | :--------------------------------------------------|
| `page`    | `1`     | None | The page number to return. The first page is `1`.   |
| `limit`   | `10`    | `100` | The number of records to return per page.          |

If you have 100 assets and you want to get the first 10, you would make a request like this:

```http
GET /video/v1/assets?page=1&limit=10
```

And if you want to get the next 10, you would increment the page parameter from `1` to `2` and make a request like this:

```http
GET /video/v1/assets?page=2&limit=10
```

### Cursor pagination

In addition to `page`/`limit`, the <ApiRefLink href="/docs/api-reference/video/assets/list-assets">List Assets</ApiRefLink> endpoint also supports cursor pagination.
Cursor pagination is a more efficient and reliable way of paginating through very large collections.

<Callout type="info" title="More to come">
  Cursor pagination is only available on the <ApiRefLink href="/docs/api-reference/video/assets/list-assets">List Assets</ApiRefLink> endpoint, but we plan to add it to more endpoints in the future. If you want it added to any specific endpoints please [let us know!](/support)
</Callout>

When you make a request to the list assets endpoint we return a `next_cursor` value.

```json
// GET /video/v1/assets
{
  "data": [
    {
      "id": "asset_id",
      "status": "ready",
      ...
    }
  ],
  "next_cursor": "eyJwYWdlX2xpbWl0IjoxMDAwLCJwYWdlX2NvdW50IjoxfQ"
}
```

Take that `next_cursor` value and make a new request to the list assets endpoint with the `cursor` parameter.

```json
// GET /video/v1/assets?cursor=eyJwYWdlX2xpbWl0IjoxMDAwLCJwYWdlX2NvdW50IjoxfQ
{
  "data": [
    {
      "id": "asset_id",
      "status": "ready",
      ...
    }
  ],
  "next_cursor": null
}
```

If `next_cursor` is `null`, you've reached the end of your list. If `next_cursor` is not `null` you can use that value to get the next page, repeating this pattern until `next_cursor` is `null`.

## API rate limits

The Mux API implements rate limits to protect you from scripts going haywire, and to ensure we remain stable for all customers. These limits are bucketed separately for each environment. This means traffic on one of your Mux environments can’t affect another. Each environment also counts toward an organization-wide cap.

<Callout type="warning" title="Exceeding the rate limit">
  When the rate limit threshold is exceeded, the API will return a HTTP status code `429`.
</Callout>

### Checking your current limit status

Every API response includes headers you can use to monitor consumption:

```
x-ratelimit-limit: 5
x-ratelimit-remaining: 3
```

`x-ratelimit-limit` is your maximum bucket size. `x-ratelimit-remaining` is how many requests remain in the bucket.

### When you hit the limit

If you make a request when your bucket is empty, Mux does not process your request. Mux will return a response with a `429 Too Many Requests` status code and the following response body.

```jsx
{
    "errors": [
      "Too many requests, retry later. Read about our Rate Limits here: https://www.mux.com/docs/core/make-api-requests#api-rate-limits"
    ]
}
```

You will need to retry your request after your request bucket starts to refill.

### Need a higher limit?

[Contact support](https://mux.com/support) with the environment, token type, and expected sustained request rate.

### Video API

There are four key concepts to understand with Mux video rate limits.

* **Endpoint type:** Mux treats POST requests differently from everything else. POST requests use one rate limit bucket, everything else uses a different bucket. This helps ensure that an issue with GET requests won’t prevent your app from creating assets.
* **Priority**: When creating an access token it can be marked **high priority** (default) or **low priority**. Use high priority tokens for your production integration. Use low priority tokens for anything where hitting a limit shouldn't affect live users, such as development environments, scripts, internal tooling, and AI agents.
* **Request bucket:** Each type of rate limit environment has a separate request bucket. Every request you make will come out of this bucket. If you make a request with an empty bucket you will receive a 429 error instead of your intended action and response.
* **Fill rate:** The request bucket automatically refills at the fill rate.

The table below includes the rate limits for high and low priority tickets making `POST`, or non-`POST` requests to `https://api.mux.com/video/`. `POST` requests include creating new <ApiRefLink href="/docs/api-reference/video/assets">Assets</ApiRefLink>, <ApiRefLink href="/docs/api-reference/video/live-streams">Live Streams</ApiRefLink>, and <ApiRefLink href="/docs/api-reference/video/direct-uploads">Uploads</ApiRefLink>. Non-`POST` requests include (but are not limited to) requests for <ApiRefLink href="/docs/api-reference/video/assets/get-asset">retrieving an asset</ApiRefLink>, <ApiRefLink href="/docs/api-reference/video/assets/update-asset-mp4-support">updating mp4 support</ApiRefLink>, and <ApiRefLink href="/docs/api-reference/video/delivery-usage/list-delivery-usage">listing delivery usage</ApiRefLink>.

| Endpoint Type | Priority | Request Bucket | Fill Rate |
| :--- | :--- | :--- | :--- |
| POST | High priority | 20 requests | 1 req/sec |
| POST | Low priority | 4 requests | 1 req/sec |
| All other methods | High priority | 100 requests | 5 req/sec |
| All other methods | Low priority | 20 requests | 1 req/sec |

### Playback

There are no limits as to the number of viewers that your streams can have, all we ask is that you let us know if you're planning an event expected to receive more than 100,000 concurrent live viewers.

### Data API

<Callout type="info" title="Data API Rate Limits">
  The Data API has not yet been updated to our new rate limits with token priorities and isolated environment buckets. Keep an eye out for it in the near future!
</Callout>

#### Monitoring

Requests against the <ApiRefLink href="/docs/api-reference/data/monitoring/list-monitoring-dimensions">Monitoring Data</ApiRefLink> APIs are rate limited to a sustained 1 request per second (RPS) with the ability to burst above this for short periods of time.

#### General

Requests against the all other <ApiRefLink href="/docs/api-reference/data/video-views">General Data</ApiRefLink> APIs are rate limited to a sustained 5 request per second (RPS) with the ability to burst above this for short periods of time.

# OpenAPI specification

The complete Mux API is described by an OpenAPI specification, available at [`https://www.mux.com/api-spec.json`](https://www.mux.com/api-spec.json). You can use this spec to generate API clients, import endpoints into tools like [Postman](/docs/core/postman), or integrate with any tooling that supports OpenAPI.
