Referencia de APIPlans

Plans

/v1/plans — productos recurrentes que tú defines y vendes a tus clientes. Ver también el concepto Plan.

El objeto Plan

{
  "id": "plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  "code": "pro-mensual",
  "name": "Plan Pro",
  "price_monthly_cents": 5000000,
  "price_annual_cents": 50000000,
  "trial_days": 7,
  "description": "Acceso completo a todas las funciones",
  "active": true,
  "created_at": "2026-08-24T15:00:00Z"
}
CampoTipo
idstring
codestring
namestring
price_monthly_centsinteger
price_annual_centsinteger | null
trial_daysinteger | null
descriptionstring | null
activeboolean
created_atdatetime (ISO-8601 UTC)

Crear un plan

POST /v1/plans

Request body

{
  "code": "pro-mensual",
  "name": "Plan Pro",
  "price_monthly_cents": 5000000,
  "price_annual_cents": 50000000,
  "trial_days": 7,
  "description": "Acceso completo a todas las funciones",
  "active": true
}
CampoRequeridoDescripción
codeCódigo único
nameNombre visible
price_monthly_centsPrecio mensual en centavos COP
price_annual_centsNoPrecio anual en centavos COP
trial_daysNoDías de prueba
descriptionNoDescripción libre
activeNoPor defecto true

Response — 201 Created

Devuelve el objeto Plan creado.

curl
curl -X POST https://api.rekurra.dev/v1/plans \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{
    "code": "pro-mensual",
    "name": "Plan Pro",
    "price_monthly_cents": 5000000,
    "trial_days": 7
  }'
JavaScript (fetch)
const res = await fetch("https://api.rekurra.dev/v1/plans", {
  method: "POST",
  headers: {
    Authorization: "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    code: "pro-mensual",
    name: "Plan Pro",
    price_monthly_cents: 5000000,
    trial_days: 7,
  }),
});
const plan = await res.json();
Python (requests)
import requests
 
res = requests.post(
    "https://api.rekurra.dev/v1/plans",
    headers={
        "Authorization": "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX",
        "Content-Type": "application/json",
    },
    json={
        "code": "pro-mensual",
        "name": "Plan Pro",
        "price_monthly_cents": 5000000,
        "trial_days": 7,
    },
)
plan = res.json()

Errores posibles

Statuserror.typeCausa
400invalid_requestFalta code, name o price_monthly_cents, o code con formato inválido
401authentication_errorAPI key inválida o ausente
409invalid_requestYa existe un plan con ese code

Listar planes

GET /v1/plans

Soporta paginación estándar: ?limit= (default 25, máx 100) y ?starting_after=<id>.

curl
curl "https://api.rekurra.dev/v1/plans?limit=25" \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"
JavaScript (fetch)
const res = await fetch("https://api.rekurra.dev/v1/plans?limit=25", {
  headers: { Authorization: "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" },
});
const { data, has_more, next_cursor } = await res.json();
Python (requests)
import requests
 
res = requests.get(
    "https://api.rekurra.dev/v1/plans",
    params={"limit": 25},
    headers={"Authorization": "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"},
)
body = res.json()

Response — 200 OK

{ "data": [ /* Plan[] */ ], "has_more": false, "next_cursor": null }

Obtener un plan

GET /v1/plans/{id}

curl
curl https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2 \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"
JavaScript (fetch)
const res = await fetch(
  "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  { headers: { Authorization: "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" } }
);
const plan = await res.json();
Python (requests)
import requests
 
res = requests.get(
    "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
    headers={"Authorization": "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"},
)
plan = res.json()

Errores posibles

Statuserror.typeCausa
404invalid_requestEl plan no existe o no pertenece a tu cuenta

Actualizar un plan

PATCH /v1/plans/{id}

Acepta cualquier subconjunto de los campos de creación.

curl
curl -X PATCH https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2 \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Plan Pro (nuevo nombre)" }'
JavaScript (fetch)
const res = await fetch(
  "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  {
    method: "PATCH",
    headers: {
      Authorization: "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ name: "Plan Pro (nuevo nombre)" }),
  }
);
const plan = await res.json();
Python (requests)
import requests
 
res = requests.patch(
    "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
    headers={
        "Authorization": "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX",
        "Content-Type": "application/json",
    },
    json={"name": "Plan Pro (nuevo nombre)"},
)
plan = res.json()

Errores posibles

Statuserror.typeCausa
400invalid_requestCampo con formato inválido
404invalid_requestEl plan no existe

Desactivar un plan

DELETE /v1/plans/{id}

Desactivación suave: marca active: false. Las suscripciones existentes que usan este plan no se ven afectadas.

curl
curl -X DELETE https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2 \
  -H "Authorization: Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"
JavaScript (fetch)
await fetch(
  "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
  {
    method: "DELETE",
    headers: { Authorization: "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX" },
  }
);
Python (requests)
import requests
 
requests.delete(
    "https://api.rekurra.dev/v1/plans/plan_01HZXK7QJ5M8Z9X2R3TVQ7A1B2",
    headers={"Authorization": "Bearer rk_live_XXXXXXXXXXXXXXXXXXXXXXXX"},
)

Response — 200 OK

Devuelve el objeto Plan con active: false.