Límites de uso

Cada llave de API puede hacer 120 solicitudes por minuto y 10,000 por día por defecto. Los límites son por llave, no por dirección IP, así que las integraciones que comparten IPs (Zapier, Make, n8n) nunca se frenan entre sí.

La API de SpaceKru (v1.1) es una API REST/JSON disponible en todos los planes de pago de SpaceKru. Sincroniza leads en ambos sentidos (upsert por external_id), añade leads a campañas, crea y mueve deals y pide seguimientos a los Empleados de IA, gestiona productos, cotizaciones, órdenes, pagos y reservas, permite que tu plataforma converse con tu Empleado de IA de Customer Service y envía webhooks firmados para 16 eventos que dicen quién causó cada cambio. URL base: https://app.spacekru.com/api/public/v1. Autenticación: llave de API Bearer (sk_live_…). Documentación: https://www.spacekru.com/es/developers. OpenAPI 3.1: https://app.spacekru.com/api/public/v1/openapi.json.

Read in English

Los límites

LímitePor defectoVentana
Solicitudes por llave por minuto120Ventanas fijas de un minuto (por reloj, UTC).
Solicitudes por llave por día10,000Día calendario en UTC. Se reinicia a las 00:00 UTC.
Respuestas de IA en curso4 por servidorSu propio pool: una ráfaga de conversaciones nunca bloquea el resto de la API.
Tamaño del body1 MBPor solicitud. Bodies más grandes responden 413 PAYLOAD_TOO_LARGE.
Tamaño de página100 registrosPor solicitud de lista (por defecto 25).
Leads por inscripción100POST /campaigns/{id}/leads

¿Necesitas más? Usa más de una llave solo cuando las integraciones sean realmente distintas, y cuéntanos tu caso por la página de contacto.

Headers de límites

Cada respuesta autenticada te dice cómo vas:

HeaderSignificado
X-RateLimit-LimitSolicitudes permitidas por minuto para esta llave.
X-RateLimit-RemainingSolicitudes que quedan en el minuto actual.
X-RateLimit-ResetSegundos hasta que se reinicie el minuto actual (una duración, no una marca de tiempo).
X-RateLimit-Daily-LimitSolicitudes permitidas por día UTC.
X-RateLimit-Daily-RemainingSolicitudes que quedan hoy.
Retry-AfterSegundos que debes esperar. Llega con 429 y 503.
X-Request-IdId de la solicitud. Menciónalo cuando contactes a soporte.
Content-LanguageIdioma de error.message (en o es).
Ejemplo
HTTP/1.1 200 OK
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 117
X-RateLimit-Reset: 41
X-RateLimit-Daily-Limit: 10000
X-RateLimit-Daily-Remaining: 9988
X-Request-Id: 5f2c9a1b7e3d

Cuando llegas a un límite: 429

  • Por encima del límite por minuto: 429 RATE_LIMITED con Retry-After = segundos hasta el siguiente minuto (máximo 60).
  • Por encima del límite diario: 429 RATE_LIMITED con Retry-After = segundos hasta las 00:00 UTC.
  • Las solicitudes rechazadas por el límite por minuto no cuentan en el límite diario.

Cuando estamos ocupados: 503

  • 503 SERVICE_BUSY: el servidor está atendiendo su máximo de solicitudes en este momento. Retry-After: 5 (15 para respuestas de conversaciones con IA). Protege a los Empleados de IA de todos los clientes, que corren en los mismos servidores.
  • 503 ELIGIBILITY_UNAVAILABLE: no pudimos verificar tu plan por un momento. Retry-After: 10.
  • Ambos son temporales y se pueden reintentar con seguridad. Las escrituras que fallaron con 503 no se aplicaron.

Reintenta con backoff

Reintenta 429 y 503 después de Retry-After segundos más un poco de espera aleatoria, para que muchos procesos no reintenten en el mismo instante. En las creaciones envía una Idempotency-Key para que un reintento nunca cree un duplicado (Idempotencia).

Node.js
const BASE = 'https://app.spacekru.com/api/public/v1';

// Retries 429 and 503 after Retry-After (+ jitter). Gives up on long waits
// (the daily limit resets at 00:00 UTC) and after 5 retries.
export async function spacekru(path, options = {}, attempt = 0) {
  const res = await fetch(`${BASE}${path}`, {
    ...options,
    headers: {
      Authorization: `Bearer ${process.env.SPACEKRU_API_KEY}`,
      'Content-Type': 'application/json',
      ...options.headers,
    },
  });

  if ((res.status === 429 || res.status === 503) && attempt < 5) {
    const retryAfter = Number(res.headers.get('Retry-After')) || 2 ** attempt;
    if (retryAfter > 60) throw new Error('Daily limit reached: resume after 00:00 UTC.');
    const waitMs = retryAfter * 1000 + Math.random() * 1000;
    await new Promise((resolve) => setTimeout(resolve, waitMs));
    return spacekru(path, options, attempt + 1);
  }

  const body = await res.json();
  if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message} (request ${body.error.request_id})`);
  return body;
}

// Usage
const page = await spacekru('/leads?limit=100');
console.log(page.data.length);
Python
import os
import random
import time

import requests

BASE = "https://app.spacekru.com/api/public/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['SPACEKRU_API_KEY']}"}


def spacekru(method, path, **kwargs):
    """Retries 429 and 503 after Retry-After (+ jitter), at most 5 times."""
    for attempt in range(6):
        r = requests.request(method, BASE + path, headers=HEADERS, timeout=30, **kwargs)
        if r.status_code in (429, 503) and attempt < 5:
            retry_after = int(r.headers.get("Retry-After", 2 ** attempt))
            if retry_after > 60:
                raise RuntimeError("Daily limit reached: resume after 00:00 UTC.")
            time.sleep(retry_after + random.random())
            continue
        body = r.json()
        if not r.ok:
            err = body["error"]
            raise RuntimeError(f"{err['code']}: {err['message']} (request {err['request_id']})")
        return body


page = spacekru("GET", "/leads", params={"limit": 100})
print(len(page["data"]))

Cómo mantenerte lejos de los límites

  • Usa webhooks en vez de consultar una y otra vez. Una suscripción a lead.created reemplaza miles de llamadas a GET /leads (Webhooks).
  • Sincroniza de forma incremental con updated_since y limit=100 en vez de releer todo (Paginación y sincronización).
  • Reparte las tareas por lotes en el tiempo en vez de lanzarlas todas a la vez.