Documentación API · v1
API REST de Kydesk Helpdesk. JSON sobre HTTPS, Bearer tokens, paginación uniforme, idempotencia y cuotas por plan. Diseñada para que construyas integraciones, automatizaciones y aplicaciones encima de tu workspace de helpdesk.
https://kydesk.kyrosrd.com/api/v1Todas las llamadas usan TLS. Tokens expirados o inválidos devuelven
401. Versionado en URL (/v1) y en header X-API-Version.
Autenticación
La API usa Bearer tokens. Genera un token desde tu panel de apps y envíalo en el header Authorization:
Authorization: Bearer kyd_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Hay dos tipos de token:
| Tipo | Origen | Cuotas |
|---|---|---|
| Developer | Generado en /developers/apps/{id} | Aplica el plan dev (rate limit + quota mensual) |
| Tenant | Generado en /t/{slug}/api-docs | Aplica las cuotas de la licencia del tenant |
Scopes
Cada token tiene scopes (read, write, *). Las llamadas GET requieren read. Las llamadas que modifican datos (POST, PATCH, DELETE) requieren write.
Quickstart
Crea tu primer ticket en menos de un minuto.
curl -X POST https://kydesk.kyrosrd.com/api/v1/tickets \ -H "Authorization: Bearer kyd_xxxx" \ -H "Content-Type: application/json" \ -d '{ "subject": "Servidor caído", "priority": "urgent", "requester_email": "alice@example.com" }'
const resp = await fetch('https://kydesk.kyrosrd.com/api/v1/tickets', { method: 'POST', headers: { 'Authorization': 'Bearer kyd_xxxx', 'Content-Type': 'application/json', }, body: JSON.stringify({ subject: 'Servidor caído', priority: 'urgent', requester_email: 'alice@example.com', }), }); const { data: ticket } = await resp.json(); console.log(ticket.code); // TK-01-00042
import requests resp = requests.post( "https://kydesk.kyrosrd.com/api/v1/tickets", headers={"Authorization": "Bearer kyd_xxxx"}, json={ "subject": "Servidor caído", "priority": "urgent", "requester_email": "alice@example.com", }, ) ticket = resp.json()["data"] print(ticket["code"]) # TK-01-00042
$ch = curl_init("https://kydesk.kyrosrd.com/api/v1/tickets"); curl_setopt_array($ch, [ CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ "Authorization: Bearer kyd_xxxx", "Content-Type: application/json", ], CURLOPT_POSTFIELDS => json_encode([ "subject" => "Servidor caído", "priority" => "urgent", ]), ]); $resp = json_decode(curl_exec($ch), true); echo $resp['data']['code'];
import ( "bytes" "encoding/json" "net/http" ) body, _ := json.Marshal(map[string]any{ "subject": "Servidor caído", "priority": "urgent", }) req, _ := http.NewRequest("POST", "https://kydesk.kyrosrd.com/api/v1/tickets", bytes.NewReader(body)) req.Header.Set("Authorization", "Bearer kyd_xxxx") req.Header.Set("Content-Type", "application/json") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close()
Manejo de errores
Todas las respuestas de error siguen el mismo formato:
{
"error": {
"type": "validation_error",
"message": "Faltan campos requeridos: subject",
"status": 422,
"request_id": "a1b2c3d4e5f6",
"missing": ["subject"]
}
}
| type | HTTP | Cuándo ocurre |
|---|---|---|
unauthorized | 401 | Token ausente o inválido |
insufficient_scope | 403 | El token no tiene el scope requerido |
developer_suspended | 403 | Cuenta de developer suspendida |
app_suspended | 403 | App suspendida o archivada |
no_subscription | 403 | Sin suscripción activa |
not_found | 404 | Recurso no existe |
precondition_failed | 412 | If-Match no coincide |
validation_error | 422 | Body inválido o campos requeridos faltantes |
quota_exceeded | 429 | Cuota mensual agotada |
rate_limit_exceeded | 429 | Rate limit superado · revisa Retry-After |
Paginación
Todos los endpoints de listado soportan paginación offset:
?page=1&per_page=25— basado en página (default)?offset=50&limit=25— basado en offsetper_pagemax 100
La respuesta incluye meta y links para navegación:
{
"data": [...],
"meta": { "total": 482, "limit": 25, "offset": 0, "has_more": true },
"links": { "first": "...", "next": "...", "prev": null, "last": "..." }
}
Filtros y orden
Cada listado expone filtros específicos. Por ejemplo, en /tickets:
?status=open,in_progress?priority=urgent?q=servidor— búsqueda en subject/code/description?assigned_to=7?created_after=2025-01-01
Orden con ?sort=campo. Prefijo - para descendente:
GET /tickets?sort=-created_at GET /companies?sort=name
Expansión de relaciones
Usa ?expand= (o ?include=) para incluir relaciones en línea. Ahorra round-trips:
GET /tickets/42?expand=company,assignee,comments
| Recurso | Relaciones disponibles |
|---|---|
| tickets | company, category, assignee, comments |
| companies | contacts, tickets |
| kb articles | category |
Selección de campos con ?fields=id,subject,status.
Idempotencia
Los endpoints POST aceptan el header Idempotency-Key. Si reenvías la misma key dentro de 24h, recibes la respuesta original sin crear duplicados.
curl -X POST https://kydesk.kyrosrd.com/api/v1/tickets \ -H "Authorization: Bearer kyd_xxxx" \ -H "Idempotency-Key: a-uuid-único-por-operación" \ -d '{ "subject": "..." }'
Rate limits & cuotas
Cada token de developer aplica los límites de su plan suscrito. Cada respuesta incluye headers informativos:
| Header | Significado |
|---|---|
X-RateLimit-Limit | Requests permitidos por minuto |
X-Quota-Used | Requests consumidos este mes |
X-Quota-Limit | Cuota mensual del plan |
X-Quota-Pct | % de cuota usada |
X-Quota-Warning | approaching-limit al pasar 80% |
Retry-After | Segundos a esperar tras un 429 |
Si superas el rate limit, recibes 429 rate_limit_exceeded. Si superas la cuota mensual, recibes 429 quota_exceeded (o sigue funcionando con header X-Quota-Status: overage si tu plan tiene overage habilitado).
Webhooks
Suscríbete a eventos para que Kydesk te notifique en tiempo real. Configúralos desde tu panel.
Eventos disponibles
ticket.createdticket.updatedticket.assignedticket.resolvedticket.escalatedsla.breachcomment.created
Verificación
Cada webhook se firma con HMAC-SHA256 usando tu secret. Verifica el header X-Kydesk-Signature:
// Node.js const crypto = require('crypto'); const sig = req.headers['x-kydesk-signature']; const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex'); if (sig !== expected) throw new Error('Invalid signature');
Reintentos
Reintentos exponenciales (1m, 5m, 30m, 1h, 6h) ante respuestas distintas a 2xx. Después de 5 fallos se desactiva el webhook.
Tickets
Campos del recurso:
| Campo | Tipo | Notas |
|---|---|---|
subject | string | Requerido al crear |
description | string | Markdown soportado |
status | enum | open · in_progress · on_hold · resolved · closed |
priority | enum | low · medium · high · urgent |
channel | enum | portal · email · phone · chat · internal |
requester_email | string | Email del solicitante |
company_id | integer | FK opcional |
category_id | integer | FK opcional |
assigned_to | integer | User ID |
tags | string | Lista separada por comas |
Comentarios
Companies
Categories
Users
Knowledge Base
SLA
Automations
Triggers disponibles: ticket.created, ticket.updated, ticket.sla_breach, ticket.escalated, ticket.resolved.
Assets
Búsqueda global
Devuelve resultados agrupados por recurso (tickets, companies, users, kb_articles).
Estadísticas
Métricas agregadas: tickets por status/priority, SLA compliance, CSAT, conteos de recursos.