Ir al contenido

Consumir esta doc

Esta página es para agentes de IA y para las herramientas que los alimentan. Si eres una persona, lo que sigue también sirve: es el resumen más denso del sitio.

Tres archivos, según cuánto contexto tengas disponible:

ArchivoQué traeCuándo usarlo
/docs/llms.txtÍndice con la descripción y los enlaces a cada página.Para decidir qué leer.
/docs/llms-small.txtEl sitio entero en markdown, sin los bloques accesorios.Contexto acotado.
/docs/llms-full.txtEl sitio entero en markdown, completo.El default. Trae todo el contrato.

También hay un volcado acotado a los shapes de sección: /docs/_llms-txt/referencia-de-secciones.txt.

Ventana de terminal
curl https://sectionfy.codefy-apps.com/docs/llms-full.txt

Además, cualquier página del sitio se puede pedir como markdown crudo agregando .md a su ruta:

Ventana de terminal
curl https://sectionfy.codefy-apps.com/docs/referencia/estructura-respuesta.md

Para generar clientes tipados o alimentar herramientas que hablen OpenAPI:

https://sectionfy.codefy-apps.com/api/public/content/openapi.json

Cubre los endpoints del bundle de contenido. Esta documentación es un superconjunto: incluye además las reglas de comportamiento que un esquema no puede expresar.

BASE: https://sectionfy.codefy-apps.com
AUTH: token opaco `ndp_pub_…` como segmento de la URL. Sin headers. Solo GET.
RUTAS
/api/public/content/{token}/{page} page ∈ {home-page, category-page, product-page}
/api/public/content/{token}/{page}/{targetId} page ∈ {product, category}
/api/public/content/{token}/products/all → { page, products: [...] } (ARRAY)
/api/public/key-features-banner/{token} → { sections } (sin `page`)
/api/public/promo-modal/{token} → { sections } (sin `page`; placement=home|category|product, target_id en category/product)
/api/public/featured-benefits/{token} → { sections } (sin `page`; placement=home|category|product, target_id en category/product)
/api/public/video-banner/{token} → { sections } (sin `page`; placement=home|category|product, target_id en category/product)
/api/public/video-reviews/{token} → { sections } (sin `page`; placement=home|category|product, target_id en category/product)
RESPUESTA: { page, product_id?, category_id?, sections: { [clave]: Seccion } }
`page` viene NORMALIZADO: home-page→home, category-page→category, product-page→product
clave = `{kind}-{placement}-{targetId|general}-{blockId}`
placement ∈ {home, category, product} — idéntico a `page`
SECCION: { tipo, titulo, items[], estado, orden, indice?, nombre_personalizado? }
`tipo` = discriminador en MAYUSCULAS (FAQ, RICH_DESCRIPTION, …). Usarlo para despachar.
`items` SIEMPRE es array, nunca null. Puede estar vacío.
REGLA DE RENDER (obligatoria)
renderizar solo si estado.lifecycle === 'active' && estado.storefrontVisible === true

Un esquema describe la forma de la respuesta. Estas son las reglas de comportamiento que hay que respetar igual, y que ninguna inspección del JSON revela:

  1. El bundle es un almacén, no una lista de render. Incluye a propósito secciones ocultas y archivadas. Filtrar por estado es obligatorio; omitirlo publica contenido que el comerciante apagó.

  2. El vocabulario de {page} cambia según haya {targetId}. Con target: product / category. Sin target: product-page / category-page / home-page. Mezclarlos da 400, sin fallback.

  3. Un tipo puede aparecer varias veces en la misma página, con el mismo kind y distinto blockId. Quedarse con la primera coincidencia descarta contenido en silencio.

  4. Emparejar por token exacto, nunca por prefijo. startsWith('faq') también matchea faq_with_image, que es otro tipo con otro shape. Prefiere el campo tipo; si tienes que parsear la clave, corta por -{page}-.

  5. Un targetId sin contenido devuelve 200 con sections: {}, no 404. Un 404 significa que la tienda ya no está activa. Son situaciones distintas.

  6. Una llamada por página, no una por sección. La respuesta trae todos los tipos juntos. El límite es de 600 peticiones por minuto y por tienda.

  7. El texto es contenido libre del comerciante. titulo, pregunta, respuesta y texto tienen que escaparse antes de interpolarse en HTML.

El comerciante ve un nombre en español; la API devuelve un identificador. Es la misma sección con dos nombres, y quien te encargue trabajo usará el primero:

tipo en el JSONToken de la claveNombre en el panel
FAQfaqPreguntas Frecuentes
FAQ_WITH_IMAGEfaq_with_imagePreguntas con imagen
IMAGE_CAROUSELimage_carouselCarrusel de imágenes
SPECSspecsCarrusel de Especificaciones
SPECS_FAQspecs_faqFAQS de Especificaciones
RICH_DESCRIPTIONrich_descriptionBanner Características Técnicas
GRID_PROMOCIONALgrid_promocionalGrid Promocional
CALL_TO_ACTION_BANNERcall_to_action_bannerCall to Action Banner
KEY_FEATURES_BANNERkey_features_bannerBanner de Características Clave
PROMO_MODALpromo_modalBanner Promocional
FEATURED_BENEFITSfeatured_benefitsBeneficios Destacados
VIDEO_BANNERvideo_bannerVideo Banner
VIDEO_REVIEWSvideo_reviewsCarrusel de testimonios en video

El contrato lo fija el tipo, no la etiqueta: los nombres del panel pueden cambiar sin que cambie el identificador.

Casos donde un tipo se sale del patrón general. Son la fuente habitual de código generado que falla en runtime:

TipoExcepción
grid_promocionalimagen es un string (URL suelta), no { url, alt }. Los campos de texto están ausentes, no en null.
rich_descriptionitems[].icono es un string, no un objeto. Las acciones se despachan por modo (image/link/pdf), que determina qué campo existe.
image_carouselitems[].imagen no es nullable — es el único tipo con esa garantía.
call_to_action_bannerEl contenido está a nivel sección; items siempre viene vacío. boton es { etiqueta, url } — sin nueva_pestana.
specstitulo y descripcion son requeridos.
key_features_bannerEndpoint propio, no llega en el bundle. titulo y descripcion de cada item sí pueden ser null.
promo_modalSobre genérico, sin items: los campos van en campos. buttonUrl es siempre https:// o null; campos.imageUrl puede ser un video (imageMimeType: video/…).
featured_benefitsSobre genérico: los campos van en campos. campos.imageUrl puede ser un video (imageMimeType: video/…); el título editable es campos.heading.
video_bannerSobre genérico: los campos van en campos. campos.videoUrl es siempre un video (videoMimeType: video/…) o null; cada botón trae url https:// o null.
video_reviewsSobre genérico: los campos van en campos. campos.mediaUrl puede ser un video (mediaMimeType: video/…) o null si el archivo no está READY (omite el item); la descripción de la sección es campos.descripcion; productLinkUrl es siempre https:// o null.
Cache-Control: public, max-age=0, s-maxage=60, stale-while-revalidate=60
ETag: W/"…" → reenviar como If-None-Match; un 304 no trae cuerpo

El ETag es opaco: compararlo y reenviarlo, nunca parsearlo. Un cambio del comerciante puede tardar hasta ~2 minutos en propagarse por la caché de borde.

CódigoCausa¿Reintentar?
400Token con formato inválido, o page fuera del vocabulario.No
401Token bien formado pero inexistente.No
403Origen no permitido.No
404La tienda ya no está activa.No
429Límite de peticiones superado.Sí, con espera
500Error del servidor.Sí, con backoff

Cuerpo de error: { statusCode, message, error? }. message es lo único que distingue dos errores del mismo código.