API
REST endpoints para conectar n8n, Zapier, scripts internos o cualquier worker con tu cuenta KANDIMA. JSON in, JSON out. Bearer auth con keys generadas desde el dashboard.
Autenticación
Generá una API key desde Dashboard → API Keys. El formato es ka_live_xxxxxxxx en producción y ka_test_xxxxxxxx en desarrollo.
Pasala como header Bearer:
Authorization: Bearer ka_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
read, write).Rate limiting
60 requests/minuto por API key. Cuando excedés el límite recibís 429 Too Many Requests. Cada respuesta incluye los headers:
X-RateLimit-Remaining: 59 X-RateLimit-Reset: 47
Necesitás más cuota? Contactanos.
Endpoints
/api/v1/statusscope: readHealth check público — no requiere Bearer auth. Útil para monitorear desde scripts antes de operar y evitar consumir quota durante outages. Cache 15s.
curl https://kandima.ai/api/v1/status
{
"status": "operational",
"api_version": "v1",
"checks": {
"database": { "status": "ok", "latency_ms": 42 }
},
"meta": {
"region": "gru1",
"env": "production",
"commit": "7qjzCz5",
"check_total_ms": 47
},
"ts": "2026-05-14T16:00:00Z"
}/api/v1/mescope: readDevuelve el perfil del usuario autenticado (plan, currency, timezone, fecha de creación) y los scopes activos de la API key.
curl https://kandima.ai/api/v1/me \ -H "Authorization: Bearer ka_live_..."
{
"user_id": "user_3DaORih5ursagiFh35CZm41SMm1",
"scopes": ["read", "write"],
"profile": {
"plan": "pro",
"currency": "USD",
"timezone": "America/Argentina/Buenos_Aires",
"created_at": "2026-04-01T12:00:00Z"
},
"api_version": "v1"
}/api/v1/creditsscope: readBalance de créditos KANDIMA, último uso, total comprado/consumido, configuración de auto-recarga, y las 5 transacciones más recientes.
curl https://kandima.ai/api/v1/credits \ -H "Authorization: Bearer ka_live_..."
{
"user_id": "user_3DaORih5ursagiFh35CZm41SMm1",
"balance": 1250,
"total_purchased": 5000,
"total_spent": 3750,
"updated_at": "2026-05-14T15:23:00Z",
"auto_topup": {
"enabled": true,
"threshold": 100,
"top_up_amount": 1000,
"last_charged_at": "2026-05-10T08:00:00Z"
},
"recent_transactions": [
{
"kind": "consume",
"feature": "ad_pack",
"amount": -50,
"balance_after": 1250,
"created_at": "2026-05-14T15:00:00Z",
"meta": { "campaign_id": "..." }
}
],
"api_version": "v1"
}/api/v1/customersscope: readLista paginada de clientes (cursor-based). Filtros: source (shopify, tienda-nube, mercado-libre). Default 25, max 100. Ordenado por id desc para que items recientes aparezcan primero.
curl "https://kandima.ai/api/v1/customers?limit=25&source=shopify" \ -H "Authorization: Bearer ka_live_..." # Paginate: curl "https://kandima.ai/api/v1/customers?cursor=842&limit=25" \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"id": 842,
"email": "alice@example.com",
"name": "Alice Morrow",
"source": "shopify",
"external_id": "shopify:kandima:alice@example.com",
"city": "Buenos Aires",
"country": "AR",
"orders_count": 4,
"revenue_total": 320.50,
"ltv_estimate": 480.75,
"aov": 80.13,
"segment": "vip",
"churn_score": 0.12,
"last_purchase_at": "2026-05-14T10:00:00Z",
"first_purchase_at": "2026-02-01T15:30:00Z",
"created_at": "2026-02-01T15:30:00Z"
}
],
"pagination": {
"limit": 25,
"next_cursor": 818,
"has_more": true
},
"api_version": "v1"
}/api/v1/integrationsscope: readEstado de cada integración OAuth conectada. Status: connected (last_sync ≤24h), stale (>24h), revoked, never_synced. Nunca devuelve tokens — solo metadata.
curl https://kandima.ai/api/v1/integrations \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"provider": "shopify",
"shop": "kandima.myshopify.com",
"scopes": ["read_orders", "read_products"],
"status": "connected",
"connected_at": "2026-04-01T12:00:00Z",
"revoked_at": null,
"last_sync_at": "2026-05-14T15:00:00Z",
"last_sync_minutes_ago": 23
}
],
"totals": {
"total": 1,
"connected": 1,
"stale": 0,
"revoked": 0,
"never_synced": 0
},
"api_version": "v1"
}/api/v1/webhooksscope: readLista los webhook subscriptions activos del usuario. Devuelve URL, eventos suscritos, fired/failed counts, last status.
curl https://kandima.ai/api/v1/webhooks \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"id": 1,
"url": "https://my-app.com/webhooks/kandima",
"events": ["purchase.created", "credits.low"],
"active": true,
"last_fired_at": "2026-05-14T15:23:00Z",
"last_status": 200,
"fail_count": 0,
"total_fired": 142,
"total_failed": 3,
"created_at": "2026-05-01T12:00:00Z"
}
],
"api_version": "v1"
}/api/v1/webhooksscope: writeCrea un webhook subscription nuevo. Devuelve el secret una sola vez (guardalo). URL debe ser HTTPS. events default = ['*'].
curl -X POST https://kandima.ai/api/v1/webhooks \
-H "Authorization: Bearer ka_live_..." \
-H "Content-Type: application/json" \
-d '{
"url": "https://my-app.com/webhooks/kandima",
"events": ["purchase.created", "credits.low"]
}'{
"id": 1,
"url": "https://my-app.com/webhooks/kandima",
"events": ["purchase.created", "credits.low"],
"active": true,
"created_at": "2026-05-14T15:00:00Z",
"secret": "whsec_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"warning": "Guardá el secret ahora — no se puede recuperar después.",
"api_version": "v1"
}/api/v1/webhooks?id=Nscope: writeRevoca el webhook subscription. No se puede deshacer.
curl -X DELETE "https://kandima.ai/api/v1/webhooks?id=1" \ -H "Authorization: Bearer ka_live_..."
{ "ok": true }/api/v1/insightsscope: readInsights AI recientes generados por el cron ai-insights-generate. Filtros: status (open/resolved/dismissed), severity (low/medium/high/critical). Default 25, max 100.
curl "https://kandima.ai/api/v1/insights?status=open&severity=high&limit=10" \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"id": 142,
"severity": "high",
"category": "ads",
"title": "ROAS cayendo en Meta últimos 7 días",
"body": "ROAS bajó de 2.4 a 1.6...",
"suggested_action": "Pausar adsets con ROAS < 1.5",
"impact_estimate": "$240 USD/día",
"status": "open",
"computed_at": "2026-05-14T08:00:00Z",
"resolved_at": null
}
],
"api_version": "v1"
}/api/v1/trackscope: writeInserta un evento custom en tu stream KANDIMA. Útil para first-party analytics sin depender de GA/Mixpanel. Event name max 64 chars (a-zA-Z0-9._-). Props JSON object max 8KB. Geo (country/region/city) se infiere automáticamente del IP.
curl -X POST https://kandima.ai/api/v1/track \
-H "Authorization: Bearer ka_live_..." \
-H "Content-Type: application/json" \
-d '{
"event": "checkout_started",
"props": { "plan": "pro", "amount_usd": 19 },
"visitor_id": "v_abc123",
"session_id": "s_xyz789",
"url": "https://my-app.com/checkout"
}'{
"ok": true,
"event_id": 142857,
"api_version": "v1"
}/api/v1/anomaliesscope: readAnomalías recientes detectadas por el cron anomaly-detect. Incluye univariate (z-score per métrica) y correlated (root-cause inference cross-métrica). Filtros: severity, days (default 7, max 90).
curl "https://kandima.ai/api/v1/anomalies?days=7&severity=high" \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"id": 12,
"metric": "roas",
"observed_value": 0.8,
"expected_value": 2.1,
"z_score": -3.2,
"direction": "down",
"severity": "high",
"detected_at": "2026-05-14T08:00:00Z",
"inferred_cause": "Ad spend up 40% sin proporcional revenue",
"confidence": 0.87,
"correlated_metrics": [
{ "metric": "ad_spend", "modz": 2.4, "direction": "up" }
]
}
],
"window_days": 7,
"api_version": "v1"
}/api/v1/profitscope: readProfit snapshots diarios del cron profit-snapshot. Default 30 días, max 365. Cada snapshot tiene revenue, refunds, ad_spend, COGS, fees, shipping, extras, plus net_revenue, operational_profit, final_profit, margin_pct.
curl "https://kandima.ai/api/v1/profit?days=7" \ -H "Authorization: Bearer ka_live_..."
{
"data": [
{
"snapshot_date": "2026-05-14",
"gross_revenue": 1250.50,
"refunds": 45.00,
"ad_spend": 320.00,
"cogs_estimate": 380.00,
"fees_estimate": 42.50,
"shipping_estimate": 65.00,
"extra_expenses": 0,
"net_revenue": 1205.50,
"operational_profit": 398.00,
"final_profit": 398.00,
"margin_pct": 31.84,
"purchase_count": 18
}
],
"totals": {
"days_returned": 7,
"gross_revenue": 7820.30,
"ad_spend": 1980.00,
"final_profit": 2340.50,
"purchase_count": 124,
"avg_margin_pct": 29.92
},
"window_days": 7,
"api_version": "v1"
}/api/v1/inventoryscope: readInventario por SKU con stock-on-hand, units sold (7d/30d), days-of-stock, trend y stockout estimado. Filtros: status (critical/low/ok/overstocked), limit (max 500). Powered by inventory_velocity cron.
curl "https://kandima.ai/api/v1/inventory?status=critical&limit=20" \ -H "Authorization: Bearer ka_live_..."
{
"items": [
{
"sku": "KND-001",
"product_name": "Pet Brush Pro",
"current_stock": 12,
"units_sold_30d": 84,
"units_sold_7d": 28,
"avg_daily_units_30d": 2.8,
"avg_daily_units_7d": 4.0,
"days_of_stock": 3.0,
"trend": "accelerating",
"status": "critical",
"estimated_stockout_at": "2026-05-17",
"computed_at": "2026-05-14T10:00:00Z"
}
],
"summary": { "total": 1, "critical": 1, "low": 0, "ok": 0, "overstocked": 0 },
"generated_at": "2026-05-14T16:30:00Z",
"api_version": "v1"
}/api/v1/reorderscope: readSmart reorder suggestions del cron smart-reorder. Cantidades sugeridas basadas en velocity + lead time + forecast con confidence score. Filtros: status (pending/ordered/dismissed), limit (max 200).
curl "https://kandima.ai/api/v1/reorder?status=pending" \ -H "Authorization: Bearer ka_live_..."
{
"items": [
{
"id": 7,
"inventory_item_id": 142,
"qty_suggested": 120,
"reason": "30d velocity 4u/día, lead time 14d, safety stock 30u",
"confidence": 0.91,
"forecast_days": 30,
"computed_at": "2026-05-14T08:30:00Z",
"status": "pending"
}
],
"generated_at": "2026-05-14T16:30:00Z",
"api_version": "v1"
}Webhook events catalog
Cuando suscribís un webhook, podés recibir cualquiera de estos eventos. Cada delivery viene firmado con HMAC SHA256 — verificá la firma antes de procesar.
import crypto from "node:crypto";
app.post("/webhooks/kandima", express.raw({ type: "application/json" }), (req, res) => {
const signature = req.headers["x-kandima-signature"];
const timestamp = req.headers["x-kandima-timestamp"];
const rawBody = req.body.toString();
const secret = process.env.KANDIMA_WEBHOOK_SECRET; // whsec_xxxx
const expected = crypto
.createHmac("sha256", secret.replace(/^whsec_/, ""))
.update(`${timestamp}.${rawBody}`)
.digest("hex");
const valid = signature.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected));
if (!valid) return res.status(401).end();
const { event, data } = JSON.parse(rawBody);
// process event...
res.status(200).end();
});purchase.createdtrigger: Stripe webhook invoice.paidUna invoice de Stripe se pagó (suscripción o top-up).
// data field of the delivery payload
{
"invoice_id": "in_xxx",
"amount": 19,
"currency": "USD",
"customer_email": "alice@example.com"
}credits.lowtrigger: Cualquier feature AI consume créditosBalance de créditos cayó debajo de 100 después de un debit.
// data field of the delivery payload
{
"balance": 45,
"threshold": 100,
"last_feature": "ad_pack"
}credits.depletedtrigger: Debit dejó balance = 0Balance llegó a 0. Próximas features AI fallarán hasta recargar.
// data field of the delivery payload
{
"balance": 0,
"last_feature": "creative_analysis",
"last_amount": 50
}credits.rechargedtrigger: Stripe webhook checkout.session.completed (mode=payment)Top-up exitoso (manual o auto-recarga).
// data field of the delivery payload
{
"credits_added": 1000,
"new_balance": 1045,
"stripe_session": "cs_xxx",
"source": "purchase"
}alert.firedtrigger: Cron alerts-evaluator detecta crossUn alert rule disparó porque un threshold se cruzó. Nivel severity puede ser low/medium/high/critical.
// data field of the delivery payload
{
"rule_id": 42,
"rule_name": "Daily ad spend > $100",
"severity": "high",
"metric": "ad_spend",
"observed": 142.50,
"threshold": 100,
"comparator": ">",
"window_hours": 24
}anomaly.detectedtrigger: Cron anomaly-detect (z-score > umbral)El cron de anomaly-detect encontró una desviación significativa (severity ≥ medium).
// data field of the delivery payload
{
"metric": "roas",
"observed": 0.8,
"expected": 2.1,
"z_score": -3.2,
"direction": "down",
"severity": "high",
"source": "univariate"
}integration.connectedtrigger: OAuth callback exitosoUna integración OAuth se acaba de conectar (Shopify, Tienda Nube, etc).
// data field of the delivery payload
{
"provider": "shopify",
"shop": "my-store.myshopify.com"
}integration.revokedtrigger: Webhook upstream app/uninstalled o revoke manualUna integración fue revocada (uninstall del usuario, expiración del token, etc).
// data field of the delivery payload
{
"provider": "tienda-nube",
"store_id": 12345,
"reason": "app_uninstalled"
}Errores
Todos los errores devuelven JSON con la forma { "error": "<code>" } y un HTTP status apropiado:
missing_authorizationNo mandaste header Authorizationinvalid_token_formatToken no empieza con ka_key_not_foundAPI key inválida o no existekey_revokedLa key fue revocadakey_expiredLa key superó su fecha de expiraciónscope_required:writeLa key no tiene el scope requeridorate_limit_exceeded60 req/min superados; esperá un minutono_dbDB no disponible (raro, ver /status)Soporte
Bug, request de feature, o necesitás endpoints adicionales? Contactanos o escribí a soporte@kandima.ai.
Estado de la API en /status.