Skip to main content

API reference

Read and change your workspace data from your own tools: companies, contacts, conversations, tasks, projects, invoices and more. The API speaks JSON over HTTPS, and every request carries a personal API token.

Machine-readable description (OpenAPI 3.1): OpenAPI JSON

The same description is served at https://<your address>/api/v1/openapi.json.

Base URL

Send requests to your organization's address, for example https://your-team.unifydesk.app/api/v1. Each token belongs to one workspace, and every request reads and writes that workspace only.

Authentication

Send the token in the Authorization header: Authorization: Bearer udk_... A missing, expired or revoked token returns 401.

Create a token

In UnifyDesk, open Settings > Access & API. Organization owners and admins, and the workspace managers, create tokens there. Creating or revoking a token needs a two-step verification within the last two hours.

Choose the modules and what the token may do in each (view, create, edit, delete). A token never gets more than its creator can do. Contract billing rates need the billing rates permission as well.

A token expires after 90 days by default, and after 365 days at most. The token is shown once: store it in a secret manager. Revoke it from the same page as soon as it is no longer needed.

Rate limits

Each token may make 60 requests per minute unless set otherwise, and each network 600. Above that the API answers 429 with Retry-After: 60.

Pagination and sorting

Lists return { data, limit, offset, nextCursor }. Use limit (1 to 100, default 50) and offset (up to 1000). Beyond that, pass the nextCursor of the previous page as cursor until it is null. Sort with order=<field>.asc or order=<field>.desc, and filter with the fields listed for each resource.

Changes and deletes

POST and PATCH take a JSON object with only the fields you set; unknown fields return 400. Add an Idempotency-Key header (up to 255 characters) to a POST so a retry returns the first result instead of creating twice.

Records that go to the trash need If-Match: "<updated_at>" from your last GET on DELETE. A record changed since then returns 412.

Errors

Errors return a JSON body { "error": "..." } with the HTTP status: 400 invalid request, 401 bad token, 403 not allowed (or a read-only subscription), 404 not found, 409 conflict, 412 stale version, 428 missing If-Match or Idempotency-Key, 429 too many requests.

Refunds

Recording an offline refund needs a signed-in person with current two-step sign-in, so it is not available through the API. Refunds stay readable, and their reason can be edited.

Resources

Each resource accepts the methods shown. The Writable column lists the methods that accept each field. Replace the example address and identifiers in angle brackets with your own.

activity

  • GET /activity
  • GET /activity/{id}

Filters: event_type, actor_id, entity_type, entity_id

FieldTypeWritable
idstring (uuid)
event_typestring
actor_idstring (uuid)
entity_typestring
entity_idstring (uuid)
created_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/activity?limit=20"

assets

  • GET /assets
  • POST /assets
  • GET /assets/{id}
  • PATCH /assets/{id}
  • DELETE /assets/{id}

Filters: asset_type_id, assigned_user_id, company_id, status

FieldTypeWritable
idstring (uuid)
namestringPOST, PATCH
asset_type_idstring (uuid)POST, PATCH
serial_numberstringPOST, PATCH
manufacturerstringPOST, PATCH
modelstringPOST, PATCH
statusstringPOST, PATCH
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
assigned_user_idstring (uuid)POST, PATCH
locationstringPOST, PATCH
purchased_atstring (date)POST, PATCH
warranty_untilstring (date)POST, PATCH
notesstringPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/assets?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example"}' "https://your-team.unifydesk.app/api/v1/assets"

companies

  • GET /companies
  • POST /companies
  • GET /companies/{id}
  • PATCH /companies/{id}
  • DELETE /companies/{id}

Filters: industry

FieldTypeWritable
idstring (uuid)
namestringPOST, PATCH
domainstringPOST, PATCH
phonestringPOST, PATCH
addressstringPOST, PATCH
industrystringPOST, PATCH
notesstringPOST, PATCH
is_vendorboolean
employee_countnumber
last_interaction_atstring (date-time)
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/companies?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example"}' "https://your-team.unifydesk.app/api/v1/companies"

contacts

  • GET /contacts
  • POST /contacts
  • GET /contacts/{id}
  • PATCH /contacts/{id}
  • DELETE /contacts/{id}

Filters: company_id

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)POST, PATCH
first_namestringPOST, PATCH
last_namestringPOST, PATCH
emailstringPOST, PATCH
phonestringPOST, PATCH
titlestringPOST, PATCH
notesstringPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/contacts?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"first_name":"Example","last_name":"Example"}' "https://your-team.unifydesk.app/api/v1/contacts"

contracts

  • GET /contracts
  • POST /contracts
  • GET /contracts/{id}
  • PATCH /contracts/{id}
  • DELETE /contracts/{id}

Filters: status, company_id, contact_id

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
contract_numberstring
titlestringPOST, PATCH
statusstring
amountnumberPOST, PATCH
currencystringPOST, PATCH
billing_cyclestringPOST, PATCH
start_datestring (date)POST, PATCH
end_datestring (date)POST, PATCH
start_atstring (date-time)POST, PATCH
end_atstring (date-time)POST, PATCH
is_all_daybooleanPOST, PATCH
renewal_datestring (date)POST, PATCH
descriptionstringPOST, PATCH
rate_per_wordnumberPOST, PATCH
is_defaultboolean
source_quote_idstring (uuid)
signed_by_namestring
signed_atstring (date-time)
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/contracts?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Example","currency":"USD"}' "https://your-team.unifydesk.app/api/v1/contracts"

conversations

  • GET /conversations
  • POST /conversations
  • GET /conversations/{id}
  • PATCH /conversations/{id}
  • DELETE /conversations/{id}

Filters: status, priority, assignee_id, company_id, contact_id, project_id, contract_id

FieldTypeWritable
idstring (uuid)
mailbox_idstring (uuid)POST, PATCH
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
project_idstring (uuid)POST, PATCH
contract_idstring (uuid)POST, PATCH
category_idstring (uuid)POST, PATCH
subjectstringPOST, PATCH
statusstringPOST, PATCH
prioritystringPOST, PATCH
assignee_idstring (uuid)POST, PATCH
team_idstring (uuid)POST, PATCH
ticket_numberstring
channelstringPOST, PATCH
first_response_atstring (date-time)
closed_atstring (date-time)
created_atstring (date-time)
updated_atstring (date-time)
resolution_category_idstring (uuid)POST, PATCH
resolution_notestringPOST, PATCH
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/conversations?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"subject":"Example"}' "https://your-team.unifydesk.app/api/v1/conversations"

credit_notes

  • GET /credit_notes
  • POST /credit_notes
  • GET /credit_notes/{id}
  • PATCH /credit_notes/{id}
  • DELETE /credit_notes/{id}

Filters: status, invoice_id

FieldTypeWritable
idstring (uuid)
credit_numberstring
invoice_idstring (uuid)POST, PATCH
company_idstring (uuid)
contact_idstring (uuid)
amountnumberPOST, PATCH
currencystringPOST, PATCH
statusstring
reasonstringPOST, PATCH
issue_datestring (date)
applied_atstring (date-time)
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/credit_notes?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"invoice_id":"<invoice id>"}' "https://your-team.unifydesk.app/api/v1/credit_notes"

documents

  • GET /documents
  • GET /documents/{id}
  • PATCH /documents/{id}
  • DELETE /documents/{id}

Filters: folder, company_id, contact_id, project_id

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)PATCH
contact_idstring (uuid)PATCH
conversation_idstring (uuid)PATCH
project_idstring (uuid)PATCH
contract_idstring (uuid)PATCH
invoice_idstring (uuid)PATCH
task_idstring (uuid)PATCH
namestringPATCH
descriptionstringPATCH
file_typestring
mime_typestring
size_bytesnumber
folderstringPATCH
versionnumber
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/documents?limit=20"

expenses

  • GET /expenses
  • POST /expenses
  • GET /expenses/{id}
  • PATCH /expenses/{id}
  • DELETE /expenses/{id}

Filters: status, category, company_id, project_id

FieldTypeWritable
idstring (uuid)
submitted_bystring
approved_bystring
company_idstring (uuid)POST, PATCH
project_idstring (uuid)POST, PATCH
contract_idstring (uuid)POST, PATCH
conversation_idstring (uuid)POST, PATCH
invoice_idstring (uuid)
categorystringPOST, PATCH
descriptionstringPOST, PATCH
amountnumberPOST, PATCH
currencystringPOST, PATCH
expense_datestring (date)POST, PATCH
statusstring
rejection_reasonstring
approved_atstring (date-time)
reimbursed_atstring (date-time)
billablebooleanPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/expenses?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"description":"Example","amount":1}' "https://your-team.unifydesk.app/api/v1/expenses"

invoices

  • GET /invoices
  • POST /invoices
  • GET /invoices/{id}
  • PATCH /invoices/{id}
  • DELETE /invoices/{id}

Filters: status, company_id, contact_id, contract_id

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
contract_idstring (uuid)POST, PATCH
project_idstring (uuid)POST, PATCH
conversation_idstring (uuid)POST, PATCH
invoice_numberstring
amountnumberPOST, PATCH
currencystringPOST, PATCH
statusstring
issue_datestring (date)POST, PATCH
due_datestring (date)POST, PATCH
paid_datestring (date)
sent_atstring (date-time)
delivered_atstring (date-time)
delivery_methodstring
payment_termsstring
memostring
customer_po_numberstringPOST, PATCH
is_recurringboolean
recurring_frequencystring
recurring_next_atstring (date)
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/invoices?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"currency":"USD"}' "https://your-team.unifydesk.app/api/v1/invoices"

opportunities

  • GET /opportunities
  • POST /opportunities
  • GET /opportunities/{id}
  • PATCH /opportunities/{id}
  • DELETE /opportunities/{id}

Filters: stage_id, company_id, contact_id, owner_id

FieldTypeWritable
idstring (uuid)
stage_idstring (uuid)POST, PATCH
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
owner_idstring (uuid)POST, PATCH
namestringPOST, PATCH
descriptionstringPOST, PATCH
amountnumberPOST, PATCH
currencystringPOST, PATCH
expected_close_datestring (date)POST, PATCH
closed_atstring (date-time)
probability_snapshotnumber
sourcestringPOST, PATCH
lost_reason_idstring (uuid)POST, PATCH
lost_reason_notestringPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/opportunities?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example"}' "https://your-team.unifydesk.app/api/v1/opportunities"

pipeline

  • GET /pipeline
  • POST /pipeline
  • GET /pipeline/{id}
  • PATCH /pipeline/{id}
  • DELETE /pipeline/{id}

Filters: stage_id, company_id, contact_id, owner_id

FieldTypeWritable
idstring (uuid)
stage_idstring (uuid)POST, PATCH
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
owner_idstring (uuid)POST, PATCH
namestringPOST, PATCH
descriptionstringPOST, PATCH
amountnumberPOST, PATCH
currencystringPOST, PATCH
expected_close_datestring (date)POST, PATCH
closed_atstring (date-time)
probability_snapshotnumber
sourcestringPOST, PATCH
lost_reason_idstring (uuid)POST, PATCH
lost_reason_notestringPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/pipeline?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example"}' "https://your-team.unifydesk.app/api/v1/pipeline"

projects

  • GET /projects
  • POST /projects
  • GET /projects/{id}
  • PATCH /projects/{id}
  • DELETE /projects/{id}

Filters: status, company_id, owner_id, contact_id, health_status

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
project_type_idstring (uuid)
stage_idstring (uuid)
namestringPOST, PATCH
descriptionstringPOST, PATCH
statusstringPOST, PATCH
start_datestring (date)POST, PATCH
end_datestring (date)POST, PATCH
start_atstring (date-time)POST, PATCH
end_atstring (date-time)POST, PATCH
is_all_daybooleanPOST, PATCH
owner_idstring (uuid)POST, PATCH
budget_amountnumberPOST, PATCH
budget_currencystringPOST, PATCH
budget_typestringPOST, PATCH
budget_alert_threshold_pctnumberPOST, PATCH
health_statusstringPOST, PATCH
source_word_countnumberPOST, PATCH
target_word_countnumberPOST, PATCH
word_count_updated_atstring (date-time)
memsource_project_uidstringPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/projects?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Example"}' "https://your-team.unifydesk.app/api/v1/projects"

purchase_orders

  • GET /purchase_orders
  • GET /purchase_orders/{id}
  • PATCH /purchase_orders/{id}
  • DELETE /purchase_orders/{id}

Filters: status, vendor_id, project_id

FieldTypeWritable
idstring (uuid)
po_numberstring
vendor_idstring (uuid)PATCH
contact_idstring (uuid)PATCH
project_idstring (uuid)PATCH
contract_idstring (uuid)PATCH
statusstring
total_amountnumber
currencystringPATCH
order_datestring (date)PATCH
expected_datestring (date)PATCH
received_datestring (date)
notesstringPATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/purchase_orders?limit=20"

quotes

  • GET /quotes
  • POST /quotes
  • GET /quotes/{id}
  • PATCH /quotes/{id}
  • DELETE /quotes/{id}

Filters: status, company_id, contact_id, opportunity_id

FieldTypeWritable
idstring (uuid)
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
opportunity_idstring (uuid)POST, PATCH
quote_numberstring
titlestringPOST, PATCH
statusstring
amountnumber
currencystringPOST, PATCH
valid_untilstring (date)POST, PATCH
line_itemsjsonPOST, PATCH
termsstring
notesstringPOST, PATCH
sent_atstring (date-time)
accepted_atstring (date-time)
accepted_by_namestring
declined_atstring (date-time)
invoice_idstring (uuid)
project_idstring (uuid)POST, PATCH
contract_idstring (uuid)POST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/quotes?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Example","currency":"USD"}' "https://your-team.unifydesk.app/api/v1/quotes"

refunds

  • GET /refunds
  • GET /refunds/{id}
  • PATCH /refunds/{id}
  • DELETE /refunds/{id}

Recording a refund needs a signed-in person with current two-step sign-in, so tokens cannot record refunds (CO51). Refunds stay readable and their reason editable.

Filters: invoice_id, credit_note_id

FieldTypeWritable
idstring (uuid)
invoice_idstring (uuid)
credit_note_idstring (uuid)
amountnumber
currencystring
reasonstringPATCH
statusstring
refunded_atstring (date-time)
refunded_bystring
created_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/refunds?limit=20"

reports

  • GET /reports
  • GET /reports/{id}
FieldTypeWritable
idstring (uuid)
namestring
descriptionstring
sourcestring
columnsjson
filtersjson
group_bystring
aggregatestring
aggregate_fieldstring
sort_bystring
sort_dirstring
created_bystring
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/reports?limit=20"

tasks

  • GET /tasks
  • POST /tasks
  • GET /tasks/{id}
  • PATCH /tasks/{id}
  • DELETE /tasks/{id}

Filters: status, priority, assignee_id, company_id, contact_id, project_id, parent_task_id

FieldTypeWritable
idstring (uuid)
conversation_idstring (uuid)POST, PATCH
project_idstring (uuid)POST, PATCH
company_idstring (uuid)POST, PATCH
contact_idstring (uuid)POST, PATCH
contract_idstring (uuid)POST, PATCH
invoice_idstring (uuid)POST, PATCH
parent_task_idstring (uuid)POST, PATCH
titlestringPOST, PATCH
descriptionstringPOST, PATCH
statusstringPOST, PATCH
prioritystringPOST, PATCH
assignee_idstring (uuid)POST, PATCH
due_datestring (date)POST, PATCH
due_atstring (date-time)POST, PATCH
is_all_daybooleanPOST, PATCH
recurrence_rulestringPOST, PATCH
estimated_hoursnumberPOST, PATCH
estimate_minutesnumberPOST, PATCH
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/tasks?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Example"}' "https://your-team.unifydesk.app/api/v1/tasks"

time_entries

  • GET /time_entries
  • POST /time_entries
  • GET /time_entries/{id}
  • PATCH /time_entries/{id}
  • DELETE /time_entries/{id}

Filters: entity_type, entity_id, user_id, billable

FieldTypeWritable
idstring (uuid)
entity_idstring (uuid)POST, PATCH
entity_typestringPOST, PATCH
user_idstring (uuid)
duration_minutesintegerPOST, PATCH
descriptionstringPOST, PATCH
billablebooleanPOST, PATCH
started_atstring (date-time)POST, PATCH
is_runningboolean
approval_statusstring
submitted_atstring (date-time)
approved_atstring (date-time)
approved_bystring
rejection_reasonstring
created_atstring (date-time)
updated_atstring (date-time)
curl -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  "https://your-team.unifydesk.app/api/v1/time_entries?limit=20"

curl -X POST -H "Authorization: Bearer $UNIFYDESK_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"entity_type":"conversation","entity_id":"<conversation id>","duration_minutes":1}' "https://your-team.unifydesk.app/api/v1/time_entries"

Questions? Contact us.