Duvo Ai Case Attachments API
Upload, list, download, and remove the files attached to a case
Upload, list, download, and remove the files attached to a case
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/duvo-ai:duvo-ai-case-attachments-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: Duvo Public Case Attachments API
description: 'Public API for programmatic access to Duvo. Authenticate with API keys created in the Duvo dashboard.
## Rate limits
Requests are counted per API key. Every response advertises the quota with the IETF RateLimit fields, so a client can self-throttle without waiting for a rejection:
- `RateLimit-Policy: "default";q=;w=` — the policy in force: `q` requests per `w` seconds.
- `RateLimit: "default";r=;t=` — the live state: `r` requests left, quota resetting in `t` seconds.
- Read the quota from the headers rather than hard-coding it; it differs per environment.
- The same numbers are also sent as `ratelimit-limit`, `ratelimit-remaining` and `ratelimit-reset`.
Once the quota is exhausted the API answers `429 Too Many Requests` with `Retry-After` set to the seconds to wait; honor it instead of retrying immediately.'
version: 1.0.0
servers:
- url: https://api.duvo.ai
description: Production server
tags:
- name: Case Attachments
description: Upload, list, download, and remove the files attached to a case
paths:
/v2/queues/{queue_id}/cases/{case_id}/attachments:
get:
operationId: listCaseAttachments
tags:
- Case Attachments
description: List the files attached to a case, oldest first. Includes attachments whose upload failed, so a missing source document is visible rather than silent.
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
attachments:
type: array
items:
type: object
properties:
id:
type: string
format: uuid
case_id:
type: string
format: uuid
filename:
type: string
mime_type:
type: string
size_bytes:
type: integer
minimum: 0
maximum: 9007199254740991
status:
type: string
enum:
- pending
- ready
- failed
failure_reason:
type:
- string
- 'null'
source:
type: string
enum:
- user
- agent
uploaded_by_user_id:
type: string
format: uuid
agent_run_id:
type:
- string
- 'null'
format: uuid
created_at:
type: string
required:
- id
- case_id
- filename
- mime_type
- size_bytes
- status
- failure_reason
- source
- uploaded_by_user_id
- agent_run_id
- created_at
additionalProperties: false
required:
- attachments
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: List Case Attachments
/v2/queues/{queue_id}/cases/{case_id}/attachments/{attachment_id}/content:
put:
operationId: uploadCaseAttachmentContent
tags:
- Case Attachments
description: Upload raw File bytes as application/octet-stream to a pending attachment reserved on this case. Maximum 20 MiB; bytes must match the reserved length. Call finalize after success. Never send JSON, base64, or an arbitrary destination URL.
requestBody:
required: true
content:
application/octet-stream:
schema:
type: string
format: binary
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
- schema:
type: string
format: uuid
in: path
name: attachment_id
required: true
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
enum:
- true
required:
- success
additionalProperties: false
'400':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
additionalProperties: false
'403':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
additionalProperties: false
'409':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
required:
- error
additionalProperties: false
summary: Upload Case Attachment Content
/v2/queues/{queue_id}/cases/{case_id}/attachments/upload-urls:
post:
operationId: createCaseAttachmentUploadUrl
tags:
- Case Attachments
description: Issue a signed URL for uploading a file to a case. The client must PUT the bytes to the returned URL with the returned Content-Type, then call the finalize endpoint so the attachment becomes visible on the case.
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
filename:
type: string
minLength: 1
maxLength: 255
mime_type:
type: string
minLength: 1
maxLength: 127
size_bytes:
type: integer
maximum: 52428800
required:
- filename
- mime_type
- size_bytes
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
attachment_id:
type: string
format: uuid
upload_url:
type: string
format: uri
upload_content_type:
type: string
expires_at:
type: string
required:
- attachment_id
- upload_url
- upload_content_type
- expires_at
additionalProperties: false
'400':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: Create Case Attachment Upload URL
/v2/queues/{queue_id}/cases/{case_id}/attachments/{attachment_id}/finalize:
post:
operationId: finalizeCaseAttachment
tags:
- Case Attachments
description: Confirm an uploaded case attachment against storage. Answers with the attachment in its settled state — `ready` when the bytes are present, `failed` (with a reason) when the upload never completed.
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
- schema:
type: string
format: uuid
in: path
name: attachment_id
required: true
description: The attachment's unique identifier
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
attachment:
type: object
properties:
id:
type: string
format: uuid
case_id:
type: string
format: uuid
filename:
type: string
mime_type:
type: string
size_bytes:
type: integer
minimum: 0
maximum: 9007199254740991
status:
type: string
enum:
- pending
- ready
- failed
failure_reason:
type:
- string
- 'null'
source:
type: string
enum:
- user
- agent
uploaded_by_user_id:
type: string
format: uuid
agent_run_id:
type:
- string
- 'null'
format: uuid
created_at:
type: string
required:
- id
- case_id
- filename
- mime_type
- size_bytes
- status
- failure_reason
- source
- uploaded_by_user_id
- agent_run_id
- created_at
additionalProperties: false
required:
- attachment
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'500':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: Finalize Case Attachment
/v2/queues/{queue_id}/cases/{case_id}/attachments/{attachment_id}/download-url:
get:
operationId: getCaseAttachmentDownloadUrl
tags:
- Case Attachments
description: Mint a short-lived signed URL for one case attachment. `disposition=inline` serves the file for the in-app viewer; `attachment` forces a download.
parameters:
- schema:
default: attachment
type: string
enum:
- inline
- attachment
in: query
name: disposition
required: false
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
- schema:
type: string
format: uuid
in: path
name: attachment_id
required: true
description: The attachment's unique identifier
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
url:
type: string
format: uri
expires_at:
type: string
required:
- url
- expires_at
additionalProperties: false
'400':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: Get Case Attachment Download URL
/v2/queues/{queue_id}/cases/{case_id}/attachments/{attachment_id}/pages/{page}:
get:
operationId: getCaseAttachmentPageImage
tags:
- Case Attachments
description: Render one page of a ready PDF case attachment to a PNG data URL for the in-app viewer. Only the first 50 pages are rendered; download the file for the rest.
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
- schema:
type: string
format: uuid
in: path
name: attachment_id
required: true
description: The attachment's unique identifier
- schema:
type: integer
minimum: 1
maximum: 9999
in: path
name: page
required: true
description: 1-based page number
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
page:
type: integer
maximum: 9007199254740991
page_count:
type: integer
maximum: 9007199254740991
rendered_page_limit:
type: integer
maximum: 9007199254740991
width:
type: integer
maximum: 9007199254740991
height:
type: integer
maximum: 9007199254740991
image:
type: string
pattern: ^data:image\/png;base64,.*
required:
- page
- page_count
- rendered_page_limit
- width
- height
- image
additionalProperties: false
'400':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'413':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'415':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'422':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: Get Case Attachment Page Image
/v2/queues/{queue_id}/cases/{case_id}/attachments/{attachment_id}:
delete:
operationId: deleteCaseAttachment
tags:
- Case Attachments
description: Remove a file from a case. The row is soft-deleted; deletion of the stored object is attempted best-effort.
parameters:
- schema:
type: string
format: uuid
in: path
name: queue_id
required: true
description: The queue's unique identifier
- schema:
type: string
format: uuid
in: path
name: case_id
required: true
description: The case's unique identifier
- schema:
type: string
format: uuid
in: path
name: attachment_id
required: true
description: The attachment's unique identifier
security:
- bearerAuth: []
responses:
'200':
description: Default Response
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
required:
- success
additionalProperties: false
'401':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
'404':
description: Default Response
content:
application/json:
schema:
type: object
properties:
error:
type: string
message:
type: string
code:
type: string
required:
- error
additionalProperties: false
summary: Delete Case Attachment
components:
securitySchemes:
bearerAuth:
type: http
scheme: bearer
description: API key authentication. Get your API key from the Duvo dashboard.