K
Kydesk
Developers

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.

Base URL: https://kydesk.kyrosrd.com/api/v1
Todas 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:

TipoOrigenCuotas
DeveloperGenerado en /developers/apps/{id}Aplica el plan dev (rate limit + quota mensual)
TenantGenerado en /t/{slug}/api-docsAplica 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"]
  }
}
typeHTTPCuándo ocurre
unauthorized401Token ausente o inválido
insufficient_scope403El token no tiene el scope requerido
developer_suspended403Cuenta de developer suspendida
app_suspended403App suspendida o archivada
no_subscription403Sin suscripción activa
not_found404Recurso no existe
precondition_failed412If-Match no coincide
validation_error422Body inválido o campos requeridos faltantes
quota_exceeded429Cuota mensual agotada
rate_limit_exceeded429Rate limit superado · revisa Retry-After

Paginación

Todos los endpoints de listado soportan paginación offset:

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:

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
RecursoRelaciones disponibles
ticketscompany, category, assignee, comments
companiescontacts, tickets
kb articlescategory

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": "..." }'
Recomendación: usa un UUID v4 generado en el cliente. Reintentos con la misma key son seguros — perfecto para webhooks o jobs.

Rate limits & cuotas

Cada token de developer aplica los límites de su plan suscrito. Cada respuesta incluye headers informativos:

HeaderSignificado
X-RateLimit-LimitRequests permitidos por minuto
X-Quota-UsedRequests consumidos este mes
X-Quota-LimitCuota mensual del plan
X-Quota-Pct% de cuota usada
X-Quota-Warningapproaching-limit al pasar 80%
Retry-AfterSegundos 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

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

GET /api/v1/tickets
POST /api/v1/tickets
GET /api/v1/tickets/{id}
PATCH /api/v1/tickets/{id}
DELETE /api/v1/tickets/{id}
POST /api/v1/tickets/{id}/assign
POST /api/v1/tickets/{id}/escalate
POST /api/v1/tickets/batch

Campos del recurso:

CampoTipoNotas
subjectstringRequerido al crear
descriptionstringMarkdown soportado
statusenumopen · in_progress · on_hold · resolved · closed
priorityenumlow · medium · high · urgent
channelenumportal · email · phone · chat · internal
requester_emailstringEmail del solicitante
company_idintegerFK opcional
category_idintegerFK opcional
assigned_tointegerUser ID
tagsstringLista separada por comas

Comentarios

GET /api/v1/tickets/{id}/comments
POST /api/v1/tickets/{id}/comments
DELETE /api/v1/tickets/{id}/comments/{cid}

Companies

GET /api/v1/companies
POST /api/v1/companies
GET /api/v1/companies/{id}
PATCH /api/v1/companies/{id}
DELETE /api/v1/companies/{id}

Categories

GET /api/v1/categories
POST /api/v1/categories
PATCH /api/v1/categories/{id}
DELETE /api/v1/categories/{id}

Users

GET /api/v1/users
POST /api/v1/users
GET /api/v1/users/{id}
PATCH /api/v1/users/{id}
DELETE /api/v1/users/{id}

Knowledge Base

GET /api/v1/kb/articles
POST /api/v1/kb/articles
GET /api/v1/kb/articles/{id}
PATCH /api/v1/kb/articles/{id}
DELETE /api/v1/kb/articles/{id}
GET /api/v1/kb/categories

SLA

GET /api/v1/sla
POST /api/v1/sla
PATCH /api/v1/sla/{id}
DELETE /api/v1/sla/{id}

Automations

GET /api/v1/automations
POST /api/v1/automations
PATCH /api/v1/automations/{id}
DELETE /api/v1/automations/{id}

Triggers disponibles: ticket.created, ticket.updated, ticket.sla_breach, ticket.escalated, ticket.resolved.

Assets

GET /api/v1/assets
POST /api/v1/assets
GET /api/v1/assets/{id}
PATCH /api/v1/assets/{id}
DELETE /api/v1/assets/{id}
GET /api/v1/search?q=consulta

Devuelve resultados agrupados por recurso (tickets, companies, users, kb_articles).

Estadísticas

GET /api/v1/stats

Métricas agregadas: tickets por status/priority, SLA compliance, CSAT, conteos de recursos.

¿Algo no funciona? Escribe a developers@kyrosrd.com o usa el API Console para diagnosticar.