---
name: "Assets API"
last_updated: 2026-08-13T00:14:46Z
type: opencloud
api_base_url: "https://apis.roblox.com/assets"
version: "0.0.1"
endpoints: 9
auth: [api-key, oauth2]
description: "You can send and receive the following request and response payloads to create assets on Roblox"
---

# Assets API

You can send and receive the following request and response payloads to create assets on Roblox. For information on the usage of the API, see the [usage guide](/docs/en-us/cloud/guides/usage-assets.md).

**API Version:** 0.0.1

**Base URL(s):**
- `https://apis.roblox.com/assets`

    ## Authentication

    Each endpoint requires one of the following authentication methods:

    - **API Key**: Pass your key in the `x-api-key` HTTP header. Create keys at [Creator Dashboard](https://create.roblox.com/dashboard/credentials).
- **OAuth 2.0**: Use Bearer token in the `Authorization` header. Authorization URL: `https://apis.roblox.com/oauth/v1/authorize`, Token URL: `https://apis.roblox.com/oauth/v1/token`

    ```
    # API Key example
    curl -H "x-api-key: YOUR_API_KEY" https://apis.roblox.com/...

    # OAuth 2.0 example
    curl -H "Authorization: Bearer YOUR_ACCESS_TOKEN" https://apis.roblox.com/...
    ```

## Endpoints

### POST `/v1/assets` [BETA]

Creates an asset with provided content and metadata.

Creates an asset with provided content and metadata.

You can't add [SocialLink](#SocialLink) objects when you create an asset. Instead, use [Update Asset](#PATCH-v1-assets-_assetId_).

Provide the [Asset](#Asset), binary asset file path, and [content type](/docs/en-us/cloud/guides/usage-assets.md#supported-asset-types-and-limits) in the form data.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`, `asset:write`

**Request Body:** `multipart/form-data` — Type: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `request` | [Asset](#asset) | Yes | Asset attributes to create. |
| `request.assetType` | `string` | No | The asset type. Required for [Create Asset](#POST-v1-assets). |
| `request.assetId` | `integer` | No | The unique identifier of the asset. Required for [Update Asset](#PATCH-v1-assets-_asset_). |
| `request.creationContext` | [CreationContext](#creationcontext) | No |  |
| `request.description` | `string` | No | The description of the asset. Limit to 1000 characters. Required for [Create Asset](#POST-v1-assets) |
| `request.displayName` | `string` | No | Display name of the asset. Required for [Create Asset](#POST-v1-assets). |
| `request.path` | `string` | No | The returned resource path of the asset. Format: `assets/{assetId}`. Example: `assets/2205400862`. |
| `fileContent` | `string` | Yes | The binary asset file path and the content type. See [Asset types and limits](/docs/en-us/cloud/guides/usage-assets.md#supported-as |

**Request example:**
```json
{
  "request": {
    "assetType": "string",
    "assetId": 0,
    "creationContext": {
      "assetPrivacy": "...",
      "creator": "...",
      "expectedPrice": "..."
    },
    "description": "string",
    "displayName": "string",
    "path": "string"
  },
  "fileContent": "string"
}
```

> **Verify mutations:** If your API key lacks the required scope (`asset:write`), this endpoint may return successfully without applying changes. Always verify mutations by re-reading the resource.

**Responses:**

- `200`: Returns the Operation ID for checking the creation status. → `Operation`
- `400`: Invalid argument. Failed to parse the request or the file. → `Status`
- `401`: The API key is not valid for this operation / You don't have the authorization.
- `500`: Server internal error / Unknown error.

**Response fields** (`Operation`)

See [Operation](#operation) in Models.

**Response example:**
```json
{
  "path": "string",
  "done": false,
  "error": {
    "code": 0,
    "message": "string"
  },
  "response": {
    "assetType": "string",
    "assetId": 0,
    "creationContext": {
      "assetPrivacy": "...",
      "creator": "...",
      "expectedPrice": "..."
    },
    "description": "string",
    "displayName": "string",
    "path": "string"
  }
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. 

**Rate Limits:** perIp: 120/minute, perApiKeyOwner: 120/minute, perOauth2Authorization: 120/minute

**Example:**
```bash
curl -X POST -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets" \
  -F "request={"assetType":"string","assetId":0,"creationContext":{"assetPrivacy":"default","creator":{"userId":"...","groupId":"..."},"expectedPrice":0},"description":"string","displayName":"string","path":"string"};type=application/json" \
  -F "fileContent=@file.bin;type=application/octet-stream"
```

### GET `/v1/assets/{assetId}` [BETA]

Retrieve specific asset metadata. Include the `readMask` parameter for additional asset metadata.

Retrieve specific asset metadata.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |
| `readMask` | query | `string` | No | Asset metadata fields to retrieve, including the description, display name, icon, social links, and previews. Examples: `description%2CdisplayName`, `previews%2CtwitchSocialLink`. |

**Responses:**

- `200`: Asset resource retrieved successfully. → `Asset`
- `400`: Malformed request, likely due to an invalid read mask.
- `401`: The API key is not valid for this operation / You don't have the authorization.
- `403`: Doesn't have the required permission.
- `404`: Asset doesn't exist.
- `500`: Server internal error / Unknown error.

**Response fields** (`Asset`)

See [Asset](#asset) in Models.

**Response example:**
```json
{
  "assetType": "string",
  "assetId": 0,
  "creationContext": {
    "assetPrivacy": "default",
    "creator": {
      "userId": "...",
      "groupId": "..."
    },
    "expectedPrice": 0
  },
  "description": "string",
  "displayName": "string",
  "path": "string"
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 120/minute, perApiKeyOwner: 120/minute, perOauth2Authorization: 120/minute

**Example:**
```bash
curl -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}"
```

### PATCH `/v1/assets/{assetId}` [BETA]

Updates an asset with provided content and metadata.

Updates an asset with provided content and metadata, including the description, display name, icon, social links, and previews. Currently can only update the content body for **Models**. Icons and Previews must be **Image** assets. Icons must have square dimensions.

Provide the [Asset](#Asset), binary asset file path, and [content type](/docs/en-us/cloud/guides/usage-assets.md#supported-asset-types-and-limits) in the form data.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`, `asset:write`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |
| `updateMask` | query | `string` | No | Asset metadata fields to update, including the description, display name, icon, and previews. Examples: `description%2CdisplayName`, `previews%2CtwitchSocialLink`. |

**Request Body:** `multipart/form-data` — Type: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `request` | [Asset](#asset) | Yes | Asset attributes to update. |
| `request.assetType` | `string` | No | The asset type. Required for [Create Asset](#POST-v1-assets). |
| `request.assetId` | `integer` | No | The unique identifier of the asset. Required for [Update Asset](#PATCH-v1-assets-_asset_). |
| `request.creationContext` | [CreationContext](#creationcontext) | No |  |
| `request.description` | `string` | No | The description of the asset. Limit to 1000 characters. Required for [Create Asset](#POST-v1-assets) |
| `request.displayName` | `string` | No | Display name of the asset. Required for [Create Asset](#POST-v1-assets). |
| `request.path` | `string` | No | The returned resource path of the asset. Format: `assets/{assetId}`. Example: `assets/2205400862`. |
| `fileContent` | `string` | Yes | The binary asset file path and the content type. See [Asset types and limits](/docs/en-us/cloud/guides/usage-assets.md#supported-as |

**Request example:**
```json
{
  "request": {
    "assetType": "string",
    "assetId": 0,
    "creationContext": {
      "assetPrivacy": "...",
      "creator": "...",
      "expectedPrice": "..."
    },
    "description": "string",
    "displayName": "string",
    "path": "string"
  },
  "fileContent": "string"
}
```

> **Verify mutations:** If your API key lacks the required scope (`asset:write`), this endpoint may return successfully without applying changes. Always verify mutations by re-reading the resource.

**Responses:**

- `200`: Returns the Operation ID for checking the update status / Returns the updated metadata fields. → `Operation`
- `400`: Invalid argument. Failed to parse the request or the file. → `Status`
- `401`: The API key is not valid for this operation / You don't have the authorization.
- `500`: Server internal error / Unknown error.

**Response fields** (`Operation`)

See [Operation](#operation) in Models.

**Response example:**
```json
{
  "path": "string",
  "done": false,
  "error": {
    "code": 0,
    "message": "string"
  },
  "response": {
    "assetType": "string",
    "assetId": 0,
    "creationContext": {
      "assetPrivacy": "...",
      "creator": "...",
      "expectedPrice": "..."
    },
    "description": "string",
    "displayName": "string",
    "path": "string"
  }
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. 

**Rate Limits:** perIp: 120/minute, perApiKeyOwner: 120/minute, perOauth2Authorization: 120/minute

**Example:**
```bash
curl -X PATCH -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}" \
  -F "request={"assetType":"string","assetId":0,"creationContext":{"assetPrivacy":"default","creator":{"userId":"...","groupId":"..."},"expectedPrice":0},"description":"string","displayName":"string","path":"string"};type=application/json" \
  -F "fileContent=@file.bin;type=application/octet-stream"
```

### POST `/v1/assets/{assetId}:archive` [BETA]

Archives the asset.

Archives the asset. Archived assets disappear from the website and are no longer usable or visible in Roblox experiences, but you can [restore](#POST-v1-assets-{assetId}:restore) them.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`, `asset:write`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |

> **Verify mutations:** If your API key lacks the required scope (`asset:write`), this endpoint may return successfully without applying changes. Always verify mutations by re-reading the resource.

**Responses:**

- `200`: Asset archived succesfully successfully. → `Asset`
- `400`: Bad request - invalid request.
- `403`: Forbidden - API key without Write scope or user doesn't have access.
- `404`: Asset not found.

**Response fields** (`Asset`)

See [Asset](#asset) in Models.

**Response example:**
```json
{
  "assetType": "string",
  "assetId": 0,
  "creationContext": {
    "assetPrivacy": "default",
    "creator": {
      "userId": "...",
      "groupId": "..."
    },
    "expectedPrice": 0
  },
  "description": "string",
  "displayName": "string",
  "path": "string"
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 100/minute, perApiKeyOwner: 100/minute, perOauth2Authorization: 100/minute

**Example:**
```bash
curl -X POST -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}:archive"
```

### POST `/v1/assets/{assetId}:restore` [BETA]

Restores an archived asset.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`, `asset:write`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |

> **Verify mutations:** If your API key lacks the required scope (`asset:write`), this endpoint may return successfully without applying changes. Always verify mutations by re-reading the resource.

**Responses:**

- `200`: Asset restored successfully. → `Asset`
- `400`: Bad request - invalid request.
- `403`: Forbidden - API key without Write scope or user doesn't have access.
- `404`: Asset not found.

**Response fields** (`Asset`)

See [Asset](#asset) in Models.

**Response example:**
```json
{
  "assetType": "string",
  "assetId": 0,
  "creationContext": {
    "assetPrivacy": "default",
    "creator": {
      "userId": "...",
      "groupId": "..."
    },
    "expectedPrice": 0
  },
  "description": "string",
  "displayName": "string",
  "path": "string"
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 100/minute, perApiKeyOwner: 100/minute, perOauth2Authorization: 100/minute

**Example:**
```bash
curl -X POST -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}:restore"
```

### GET `/v1/assets/{assetId}/versions/{versionNumber}` [BETA]

Get Asset Version

Retrieve a specific asset version by the asset ID and the version number.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |
| `versionNumber` | path | `string` | Yes | The version number. |

**Responses:**

- `200`: Asset version retrieved successfully. → `AssetVersion`
- `403`: Forbidden - API key without Read scope or user doesn't have access.
- `404`: Asset or Asset Version not found.

**Response fields** (`AssetVersion`)

See [AssetVersion](#assetversion) in Models.

**Response example:**
```json
{
  "creationContext": {
    "assetPrivacy": "default",
    "creator": {
      "userId": "...",
      "groupId": "..."
    },
    "expectedPrice": 0
  },
  "path": "string",
  "moderationResult": {
    "moderationState": "string"
  },
  "published": false
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 100/minute, perApiKeyOwner: 100/minute, perOauth2Authorization: 100/minute

**Example:**
```bash
curl -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}/versions/{VERSIONNUMBER}"
```

### GET `/v1/assets/{assetId}/versions` [BETA]

List Asset Versions of an Asset

List all versions of a specific asset, with optional pagination.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |
| `maxPageSize` | query | `integer` | No | Specifies the number of asset versions to include in the response. Valid values range from 1 to 50 (inclusive). Defaults to 8 when not provided. |
| `pageToken` | query | `string` | No | A token for pagination. The value is obtained from a previous request and allows for retrieving the next page of asset versions. |

**Responses:**

- `200`: Asset versions listed successfully. → `AssetVersion[]`
- `400`: Bad request - invalid parameters.
- `403`: Forbidden - API key without Read scope or user doesn't have access.
- `404`: Asset not found.

**Response fields** (`AssetVersion[]`)

See [AssetVersion](#assetversion) in Models.

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 100/minute, perApiKeyOwner: 100/minute, perOauth2Authorization: 100/minute

**Example:**
```bash
curl -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}/versions"
```

### POST `/v1/assets/{assetId}/versions:rollback` [BETA]

Rollback an asset to a previous version.

Rollback an asset to a specific previous version.

 Provide the asset version path in the form data.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`, `asset:write`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `assetId` | path | `string` | Yes | The unique identifier of the asset. |

**Request Body:** `multipart/form-data` — Type: `object`

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `assetVersion` | `string` | Yes | The asset version path in the format of `assets/{assetId}/versions/{versionNumber}`. |

**Request example:**
```json
{
  "assetVersion": "string"
}
```

> **Verify mutations:** If your API key lacks the required scope (`asset:write`), this endpoint may return successfully without applying changes. Always verify mutations by re-reading the resource.

**Responses:**

- `200`: Asset rolled back successfully. → `AssetVersion`
- `400`: Bad request - invalid request body.
- `403`: Forbidden - API key without Write scope or user doesn't have access.
- `404`: Asset or Asset Version not found.

**Response fields** (`AssetVersion`)

See [AssetVersion](#assetversion) in Models.

**Response example:**
```json
{
  "creationContext": {
    "assetPrivacy": "default",
    "creator": {
      "userId": "...",
      "groupId": "..."
    },
    "expectedPrice": 0
  },
  "path": "string",
  "moderationResult": {
    "moderationState": "string"
  },
  "published": false
}
```

**Error handling:** `403`: Verify your API key has the required scopes listed above. 

**Rate Limits:** perIp: 100/minute, perApiKeyOwner: 100/minute, perOauth2Authorization: 100/minute

**Example:**
```bash
curl -X POST -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/assets/{ASSETID}/versions:rollback" \
  -F "assetVersion=string"
```

### GET `/v1/operations/{operationId}` [BETA]

Get the result of an asset creation or update.

Get the result of an asset creation or update using the returned Operation ID. Requires **Read** for the API key permission and **asset:read** for OAuth 2.0 apps.

**Auth:** API Key (`x-api-key` header) or OAuth 2.0 Bearer token

**Scopes:** `asset:read`

**Parameters:**

| Name | In | Type | Required | Description |
|------|-----|------|----------|-------------|
| `operationId` | path | `string` | Yes | The unique identifier of the operation. |

**Responses:**

- `200`: Operation result retrieved successfully. → `Operation`
- `400`: Invalid argument. Failed to parse the request or the file. → `Status`
- `401`: The API key is not valid for this operation / You don't have the authorization.
- `500`: Server internal error / Unknown error.

**Response fields** (`Operation`)

See [Operation](#operation) in Models.

**Response example:**
```json
{
  "path": "string",
  "done": false,
  "error": {
    "code": 0,
    "message": "string"
  },
  "response": {
    "assetType": "string",
    "assetId": 0,
    "creationContext": {
      "assetPrivacy": "...",
      "creator": "...",
      "expectedPrice": "..."
    },
    "description": "string",
    "displayName": "string",
    "path": "string"
  }
}
```

**Error handling:** `401`: Check that your API key/token is valid and not expired. 

**Rate Limits:** perIp: 300/minute, perApiKeyOwner: 300/minute, perOauth2Authorization: 300/minute

**Example:**
```bash
curl -H "x-api-key: $ROBLOX_API_KEY" \
  "https://apis.roblox.com/assets/v1/operations/{OPERATIONID}"
```

## Models

### Asset

Represents an asset.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `assetType` | `string` | No | The asset type. Required for [Create Asset](#POST-v1-assets). |
| `assetId` | `integer` | No | The unique identifier of the asset. Required for [Update Asset](#PATCH-v1-assets-_asset_). |
| `creationContext` | `CreationContext` | No |  |
| `description` | `string` | No | The description of the asset. Limit to 1000 characters. Required for [Create Asset](#POST-v1-assets). |
| `displayName` | `string` | No | Display name of the asset. Required for [Create Asset](#POST-v1-assets). |
| `path` | `string` | No | The returned resource path of the asset. Format: `assets/{assetId}`. Example: `assets/2205400862`. |
| `revisionId` | `string` | No | Revision ID of the asset. Equivalent to `versionNumber`. Every change of the asset automatically commits a new version. The format is an integer string. Example: `1`. |
| `revisionCreateTime` | `string` | No | The creation timestamp of the current revision. |
| `moderationResult` | `ModerationResult` | No |  |
| `icon` | `string` | No | The resource path for the icon. |
| `previews` | `Preview[]` | No | A list of previews, each with an asset path and alt text. Previews must be **Image** assets. |
| `state` | `State` | No |  |
| `socialLink` | `SocialLink` | No |  |

### AssetVersion

An asset version.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `creationContext` | `CreationContext` | No |  |
| `path` | `string` | No | The returned resource path of the asset version. Format: `assets/{assetId}/versions/{version}`. Example: `assets/2205400862/versions/1`. |
| `moderationResult` | `ModerationResult` | No |  |
| `published` | `boolean` | No | Only applies to place asset types. Indicates if the place has been published or not. |

### CreationContext

The context of creation that is not part of the asset content, such as metadata and creator information. Required for [Create Asset](#POST-v1-assets).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `assetPrivacy` | `AssetPrivacy` | No | Desired privacy setting for the asset on creation. Only applies to asset types that support privacy override. |
| `creator` | `Creator` | No |  |
| `expectedPrice` | `integer` | No | Expected asset upload fee in Robux. When the actual price is more than expected, the operation fails with a 400 error. |

### Creator

Represents a creator.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `userId` | `integer` | No | The User ID the creator. Required if the asset is individual-user-owned. |
| `groupId` | `integer` | No | The Group ID. Required if the asset is group-owned. |

### ModerationResult

The moderation result of the asset. 

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `moderationState` | `string` | No | The moderation state of the asset. Can be `Reviewing`, `Rejected`, or `Approved`. |

### Operation

This resource represents a long-running operation that is the result of a network API call.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `path` | `string` | No | The server-assigned resource path. The default format is `operations/{operation_id}`. |
| `done` | `boolean` | No | If `false`, the operation is still in progress. If `true`, the operation is completed. |
| `error` | `Status` | No |  |
| `response` | `Asset` | No |  |

### Preview

An asset preview.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `asset` | `string` | No | The preview asset path. |
| `altText` | `string` | No | Alt text for the preview asset. |

### SocialLink

A social media link for the asset. Maximum of three per asset. Object name can be any of: <ul><li>`facebookSocialLink`</li><li>`twitterSocialLink`</li><li>`youtubeSocialLink`</li><li>`twitchSocialLink`</li><li>`discordSocialLink`</li><li>`githubSocialLink`</li><li>`robloxSocialLink`</li><li>`guildedSocialLink`</li><li>`devForumSocialLink`</li></ul>For syntax, see the sample request under [Update Asset](#PATCH-v1-assets-_assetId_).

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `title` | `string` | No | An optional title for the social media link. Not used on the Creator Hub. |
| `uri` | `string` | No | The URI for the social media link. Must match the expected format for the type of link. For example, the title for a `twitchSocialLink` object must be of the format `https://twitch.tv/your-channel`. |

### Status

The logical error model explaining the error status.

| Property | Type | Required | Description |
|----------|------|----------|-------------|
| `code` | `integer` | No | The HTTP status code. |
| `message` | `string` | No | The error message. |