ID del formulario

JavaScript y fetch

El endpoint de envíos en detalle: formatos de cuerpo, cabeceras, CORS, respuestas e idempotencia.

Cualquier código que pueda enviar una petición HTTP puede enviar a Ikiform. Envía JSON, FormData o datos urlencoded a https://ikiform.com/f/<formId> y lee una respuesta JSON. El SDK lo envuelve en una función, pero es opcional. Para una configuración paso a paso en un stack concreto, consulta Guías por plataforma.

Con fetch

const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
  method: "POST",
  headers: { "Content-Type": "application/json", Accept: "application/json" },
  body: JSON.stringify({
    name: "Ada Lovelace",
    email: "ada@example.com",
    message: "Hello",
  }),
});

const result = await response.json();
if (!result.ok) console.error(result.error.code, result.error.fields);

Pruébalo

ID del formulario
Campos
Cuerpo
Clave de idempotencia
curl https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx \
  -H "Content-Type: application/json" \
  -d '{"name":"Ada Lovelace","email":"ada@example.com","message":"Hello from the Ikiform docs."}'

Escribe el ID de tu formulario para enviarlo como una petición real.

Endpoints

MétodoRutaQué hace
POST/f/<formId>Crea un envío
OPTIONS/f/<formId>Preflight de CORS, siempre 204
GET/f/<formId>/schemaLa definición pública de los campos del formulario, consulta shadcn/ui
GET/f/<formId>/thanksLa página de agradecimiento alojada
GET/f/<formId>/challengeEl frame de verificación humana de Ikiform, que usa el SDK

Abrir /f/<formId> en una pestaña del navegador es un GET, que responde 404 not_found. Es lo esperado: el endpoint solo acepta envíos.

Formatos de cuerpo

Content-TypeFormaNotas
application/json y tipos +jsonUn objeto JSONLos valores pueden ser cadenas, números, booleanos, arrays y objetos, con un anidamiento máximo de 3 niveles contando el objeto principal
application/x-www-form-urlencodedPares de nombre y valorLos nombres repetidos y name[] se convierten en arrays
multipart/form-dataPares de nombre y valorIgual que urlencoded; los archivos reales se rechazan
Cualquier otro415 unsupported_media_type

Los cuerpos deben ser UTF-8. Un charset distinto de utf-8 recibe 415 unsupported_charset, y los bytes que no son UTF-8 válido reciben el mismo código. Un array JSON o un cuerpo mal formado recibe 400 invalid_body.

Cabeceras

Cabeceras de la petición

CabeceraObligatoriaEfecto
Content-TypeSíElige el parser del cuerpo, consulta arriba
AcceptNoapplication/json fuerza una respuesta JSON, consulta JSON o una redirección
Idempotency-KeyNoHace que los reintentos sean seguros, hasta 255 caracteres, consulta Idempotencia
AuthorizationNoBearer ik_sk_... o Bearer ik_pub_..., consulta Desde un servidor
Origin, RefererLos envían los navegadoresSe comparan con los dominios permitidos del formulario

Cabeceras de la respuesta

CabeceraCuándoValor
X-Request-IdCada respuestareq_..., repetido como request_id en los cuerpos de error
Retry-After429Segundos hasta que se permite el siguiente envío
Location303 éxito en el navegadorTu redirección o la página de agradecimiento alojada
Access-Control-Allow-OriginCuando la petición tiene un OriginEl origen de la propia petición
Access-Control-Expose-HeadersCon CORSX-Request-Id, Retry-After, para que el código del navegador pueda leer ambas
Cache-ControlÉxitono-store

CORS

El endpoint de envíos acepta envíos cross-origin desde cualquier sitio. Los preflights siempre tienen éxito y devuelven el origen de la petición. No se usan cookies ni credenciales, así que CORS no es lo que protege tu formulario: lo protegen los dominios permitidos. Con dominios permitidos configurados, un envío desde otro sitio se guarda como spam o se rechaza, según el ajuste del formulario. Consulta Dominios permitidos.

Preflight
OPTIONS /f/frm_xxxxxxxxxxxxxxxx HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: content-type

HTTP/1.1 204 No Content
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: POST
Access-Control-Allow-Headers: Content-Type, Accept, Idempotency-Key, Authorization
Access-Control-Max-Age: 86400
Vary: Origin
La API REST bajo /api/v1 es distinta: no envía cabeceras CORS y responde a los preflights del navegador con 405, así que una clave secreta nunca se puede usar desde una página web.

Respuestas

El éxito es 201 con el id del nuevo envío. Los errores usan el mismo formato en todas partes, con los errores de campo indexados por id de campo cuando falla la validación. Todos los códigos están en Errores.

{ "ok": true, "id": "sub_01k7v2c9t3e8m5q4x6z0a1b2c3" }
Un envío que puntúa como spam igualmente recibe 201. El spam se guarda aparte y nunca llega a tus webhooks ni a tu bandeja de entrada.

Idempotencia

Envía una cabecera Idempotency-Key, o un campo _idempotency, para que los reintentos sean seguros. Las claves tienen hasta 255 caracteres y valen para el formulario durante 24 horas. Si se envían ambas, gana la cabecera.

Reintento conResultado
La misma clave y los mismos camposSe repite la primera respuesta. No se crea un segundo envío.
La misma clave y campos distintos422 idempotency_mismatch
La misma clave mientras la primera petición sigue en curso409 idempotency_in_progress

Los envíos que fallan antes de guardarse, como los errores de validación, no conservan la clave, así que puedes corregir los datos y reintentar con la misma clave. Un bucle de reintentos seguro:

retry.js
const key = crypto.randomUUID();

async function send(attempt = 1) {
  const response = await fetch("https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx", {
    method: "POST",
    headers: { "Content-Type": "application/json", "Idempotency-Key": key },
    body: JSON.stringify({ email: "ada@example.com" }),
  }).catch(() => null);
  if (response && response.status < 500 && response.status !== 429) return response.json();
  if (attempt === 3) throw new Error("Ikiform is unreachable");
  const wait = Number(response?.headers.get("Retry-After")) || attempt * 2;
  await new Promise((resolve) => setTimeout(resolve, wait * 1000));
  return send(attempt + 1);
}

Guías por plataforma

Frameworks

Generadores de sitios estáticos

Creadores de sitios