POST /api/v1/media
Authentication
Use an agent API key and secret.
Request body
Media upload
Required: Yes.
multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
| files | string (binary) | Yes | File to upload. Only the first file is used. Size and extension limits come from the upload settings. |
| inline | string | No | Set to 'true' to store the file with an inline disposition (e.g. an inline image) instead of as an attachment. |
| linked_model | string | No | Name of the model the uploaded media is linked to, e.g. messages. help_articles stores the file as publicly served media and requires the help_center:manage permission. example: "messages" |
Responses
200
Successful media upload response
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "success" |
| data | object | No | |
| data.id | integer | No | example: 123 |
| data.created_at | string (date-time) | No | example: "2025-08-28T10:00:00Z" |
| data.updated_at | string (date-time) | No | example: "2025-08-28T10:00:00Z" |
| data.uuid | string | No | example: "550e8400-e29b-41d4-a716-446655440000" |
| data.store | string (enum) | No | enum: ["s3", "fs"] example: "fs" |
| data.filename | string | No | example: "example.jpg" |
| data.content_type | string | No | example: "image/jpeg" |
| data.content_id | string | No | example: "" |
| data.model_id | integer | No | nullable: true example: 456 |
| data.model_type | string | No | nullable: true example: "messages" |
| data.disposition | string (enum) | No | enum: ["inline", "attachment"] nullable: true example: "attachment" |
| data.size | integer | No | example: 102400 |
| data.meta | object | No | nullable: true example: {"width": 800, "height": 600} |
| data.private | boolean | No | Private media is served only through signed URLs example: true |
| data.url | string | No | example: "/uploads/550e8400-e29b-41d4-a716-446655440000" |
400
Invalid request
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "error" |
| message | string | No | Error message example: "Invalid request" |
| data | unspecified | No | Additional error data nullable: true |
| error_type | string (enum) | No | enum: ["GeneralException", "PermissionException", "InputException", "DataException", "NetworkException", "NotFoundException", "ConflictException", "UnauthorizedException", "RateLimitException"] |
401
Unauthorized
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "error" |
| message | string | No | Error message example: "Invalid request" |
| data | unspecified | No | Additional error data nullable: true |
| error_type | string (enum) | No | enum: ["GeneralException", "PermissionException", "InputException", "DataException", "NetworkException", "NotFoundException", "ConflictException", "UnauthorizedException", "RateLimitException"] |
403
Forbidden
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "error" |
| message | string | No | Error message example: "Invalid request" |
| data | unspecified | No | Additional error data nullable: true |
| error_type | string (enum) | No | enum: ["GeneralException", "PermissionException", "InputException", "DataException", "NetworkException", "NotFoundException", "ConflictException", "UnauthorizedException", "RateLimitException"] |
413
File too large
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "error" |
| message | string | No | Error message example: "Invalid request" |
| data | unspecified | No | Additional error data nullable: true |
| error_type | string (enum) | No | enum: ["GeneralException", "PermissionException", "InputException", "DataException", "NetworkException", "NotFoundException", "ConflictException", "UnauthorizedException", "RateLimitException"] |
500
Internal server error
Content type: application/json.
| Field | Type | Required | Description |
|---|---|---|---|
| status | string | No | example: "error" |
| message | string | No | Error message example: "Invalid request" |
| data | unspecified | No | Additional error data nullable: true |
| error_type | string (enum) | No | enum: ["GeneralException", "PermissionException", "InputException", "DataException", "NetworkException", "NotFoundException", "ConflictException", "UnauthorizedException", "RateLimitException"] |
Specification
Download the complete OpenAPI specification.
OpenAPI definition for this endpoint
openapi: 3.0.0
info:
title: Libredesk API
description: >-
REST API documentation for Libredesk helpdesk system.
## Authentication
The Libredesk API supports two authentication methods:
### 1. Basic Authentication
Use your API key and secret with Basic authentication:
```
Authorization: Basic <base64_encoded_api_key:api_secret>
```
### 2. Token Authentication
Use your API key and secret with token authentication:
```
Authorization: token api_key:api_secret
```
To obtain API credentials, generate them from your agent profile in the
Libredesk dashboard.
version: 1.0.0
servers:
- url: http://localhost:8080
description: Local development server
security:
- basicAuth: []
- tokenAuth: []
paths:
/api/v1/media:
post:
tags:
- Media
summary: Media Upload
operationId: handleMediaUpload
requestBody:
description: Media upload
required: true
content:
multipart/form-data:
schema:
type: object
properties:
files:
type: string
format: binary
description: >-
File to upload. Only the first file is used. Size and
extension limits come from the upload settings.
inline:
type: string
description: >-
Set to 'true' to store the file with an inline disposition
(e.g. an inline image) instead of as an attachment.
linked_model:
type: string
description: >-
Name of the model the uploaded media is linked to, e.g.
`messages`. `help_articles` stores the file as publicly
served media and requires the `help_center:manage`
permission.
example: messages
required:
- files
responses:
'200':
description: Successful media upload response
content:
application/json:
schema:
$ref: '#/components/schemas/MediaResponse'
'400':
description: Invalid request
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'401':
description: Unauthorized
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'403':
description: Forbidden
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'413':
description: File too large
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
'500':
description: Internal server error
content:
application/json:
schema:
$ref: '#/components/schemas/ErrorResponse'
security:
- basicAuth: []
- tokenAuth: []
components:
schemas:
MediaResponse:
type: object
properties:
status:
type: string
example: success
data:
$ref: '#/components/schemas/Media'
ErrorResponse:
type: object
description: Error response format
properties:
status:
type: string
example: error
message:
type: string
description: Error message
example: Invalid request
data:
nullable: true
description: Additional error data
error_type:
type: string
enum:
- GeneralException
- PermissionException
- InputException
- DataException
- NetworkException
- NotFoundException
- ConflictException
- UnauthorizedException
- RateLimitException
Media:
type: object
properties:
id:
type: integer
example: 123
created_at:
type: string
format: date-time
example: '2025-08-28T10:00:00Z'
updated_at:
type: string
format: date-time
example: '2025-08-28T10:00:00Z'
uuid:
type: string
example: 550e8400-e29b-41d4-a716-446655440000
store:
type: string
example: fs
enum:
- s3
- fs
filename:
type: string
example: example.jpg
content_type:
type: string
example: image/jpeg
content_id:
type: string
example: ''
model_id:
type: integer
nullable: true
example: 456
model_type:
type: string
nullable: true
example: messages
disposition:
type: string
nullable: true
example: attachment
enum:
- inline
- attachment
size:
type: integer
example: 102400
meta:
type: object
example:
width: 800
height: 600
nullable: true
private:
type: boolean
example: true
description: Private media is served only through signed URLs
url:
type: string
example: /uploads/550e8400-e29b-41d4-a716-446655440000
securitySchemes:
basicAuth:
type: http
scheme: basic
description: >-
Basic authentication using base64 encoded API key and secret. Format:
`Authorization: Basic <base64(api_key:api_secret)>`
tokenAuth:
type: apiKey
name: Authorization
in: header
description: >-
Token authentication using API key and secret. Format: `Authorization:
token api_key:api_secret`
