# Orden de creación

> Qué tiene que existir antes de cada llamada, de dónde sale cada id, la secuencia de los flujos habituales y los errores que aparecen cuando se salta un paso.

Casi todo en Memberfy depende de algo creado antes: la lección necesita el módulo, el módulo el curso, el curso el espacio. Llamar a la API fuera de orden no rompe nada, pero cada llamada adelantada se rechaza. Esta guía muestra el orden correcto y el id que pasa de una llamada a la siguiente.

## El mapa de dependencias

<div class="flow">
<div class="flow-row"><span class="flow-label">Estructura y contenido</span><span class="flow-node">Comunidad</span><span class="flow-arrow">→</span><span class="flow-node">Sección</span><span class="flow-arrow">→</span><span class="flow-node">Espacio (módulo)</span><span class="flow-arrow">→</span><span class="flow-node">Publicación · Evento · Imagen</span></div>
<div class="flow-row"><span class="flow-label">Cursos</span><span class="flow-node">Espacio de Cursos</span><span class="flow-arrow">→</span><span class="flow-node">Curso</span><span class="flow-arrow">→</span><span class="flow-node">Módulo</span><span class="flow-arrow">→</span><span class="flow-node">Lección</span></div>
<div class="flow-row"><span class="flow-label">Venta</span><span class="flow-node">Cobro aprobado</span><span class="flow-arrow">→</span><span class="flow-node">Vender y retirar</span></div>
<div class="flow-row"><span class="flow-label">Suscripción</span><span class="flow-node">Opción de cobro</span><span class="flow-arrow">→</span><span class="flow-node">Plan</span><span class="flow-arrow">→</span><span class="flow-node">Adicionales del plan</span><span class="flow-arrow">→</span><span class="flow-node">Downsell</span></div>
<div class="flow-row"><span class="flow-label">Acceso</span><span class="flow-node">Plan o producto</span><span class="flow-arrow">→</span><span class="flow-node">Acceso del espacio</span></div>
<div class="flow-row"><span class="flow-label">Descuento</span><span class="flow-node">Productos</span><span class="flow-arrow">→</span><span class="flow-node">Cupón</span></div>
</div>

Dicho de otra forma:

| Para crear… | Necesitas antes… | Y pasas |
|---|---|---|
| Espacio | una sección | `sectionId` |
| Publicación, evento, curso, imagen | un espacio | `spaceId` |
| Módulo de curso | un curso | `courseId` |
| Lección | un módulo | `moduleId` |
| Plan | las opciones de cobro (productos `SUBSCRIPTION`) | `productIds` |
| Adicional en el plan | el plan, y un producto mensual que no sea opción de ningún plan | `addOnProductIds` |
| Acceso a un espacio por plan o producto | el plan o el producto | `access.subscriptionGroupIds`, `access.productIds` |
| Cupón solo para algunos productos | los productos | `applicableProducts` |
| Cualquier venta o retiro | Información Empresarial y cuenta de cobro aprobadas | — |

En todas las llamadas de abajo van `Authorization` y `X-CommunityId`. Consulta [Autenticación](/api/autenticacao) y [X-CommunityId](/api/x-community-id).

## Curso

1. **Sección** (si todavía no hay ninguna): [`POST /api/sections`](/api/referencia/sections-spaces/post-sections) con `title` y `visibility`. Guarda `data.id` como `sectionId`.
2. **Espacio de Cursos**: [`POST /api/spaces`](/api/referencia/sections-spaces/post-spaces) con `sectionId`, `title` y `module: "courses"`. Guarda el `spaceId`.
3. **Curso**: [`POST /api/courses`](/api/referencia/courses/post-courses) con `communityId` (el mismo de la cabecera), `spaceId`, `title`, `slug` y `level` (`beginner`, `intermediate`, `advanced`). Nace como borrador. Guarda el `courseId`.
4. **Módulos**: [`POST /api/courses/module`](/api/referencia/courses/post-courses-module) con `courseId` y `title`, uno por módulo. Guarda cada `moduleId`.
5. **Lecciones**: [`POST /api/courses/lesson`](/api/referencia/courses/post-courses-lesson) con `moduleId`, `title` y `type` (`text`, `image`, `video`, `link`).
6. **Publicar**: [`PUT /api/courses/{id}`](/api/referencia/courses/put-courses-by-id) con `status: "published"`. Solo un curso publicado acepta matrículas.

Para ajustarlo después: [`PUT`](/api/referencia/courses/put-courses-module-by-module-id) y [`DELETE /api/courses/module/{moduleId}`](/api/referencia/courses/delete-courses-module-by-module-id) renombran, reordenan y eliminan un módulo (con sus clases); [`PUT`](/api/referencia/courses/put-courses-lesson-by-lesson-id) y [`DELETE /api/courses/lesson/{lessonId}`](/api/referencia/courses/delete-courses-lesson-by-lesson-id) cambian el título, el tipo, la duración y el orden de una clase, la llevan a otro módulo del mismo curso (`moduleId`) y la eliminan. Eliminar conserva el progreso de quien ya la vio.

Para vender el curso, sigue con un producto que abra el espacio (consulta [Evento](#evento), pasos 3 y 4, que valen igual).

## Mentoría

Un grupo con su propio tablón, encuentros y cobro mensual. (Con la [duración del contrato](/monetizacao/duracao-do-contrato), la opción del paso 3 incorpora `commitmentMonths`.)

1. **Espacio privado del grupo**: [`POST /api/spaces`](/api/referencia/sections-spaces/post-spaces) con `module: "feed"` y `visibility: "private"`. Guarda el `spaceId`.
2. **Encuentros**: [`POST /api/events`](/api/referencia/events/post-events), uno por encuentro, con `spaceId`, `title`, `slug`, `type: "online"`, `startTime` y `endTime`.
3. **Opción de cobro**: [`POST /api/products`](/api/referencia/products/post-communities-by-community-id-products) con `type: "SUBSCRIPTION"`, `title`, `price`, `billingInterval: "MONTHLY"` y `allowedPaymentMethods`. Guarda el `id` del producto.
4. **Plan**: [`POST /api/subscription-groups`](/api/referencia/subscriptions/post-communities-by-community-id-subscription-groups) con `name` y `productIds: [<id del paso 3>]`. Guarda el `id` del plan.
5. **Abrir el espacio al plan**: [`PUT /api/spaces/{id}`](/api/referencia/sections-spaces/put-spaces-by-id) con `access: { "subscriptionGroupIds": [<id del plan>] }`.

El paso 5 solo funciona después del 4: el plan tiene que existir para poder citarlo en el acceso.

## Evento

Un evento presencial con entrada de pago y aviso en el Feed.

1. **Espacio de Eventos**: [`POST /api/spaces`](/api/referencia/sections-spaces/post-spaces) con `module: "events"`.
2. **Evento**: [`POST /api/events`](/api/referencia/events/post-events) con `spaceId`, `title`, `slug`, `type: "in_person"`, `startTime`, `endTime` y la dirección (`street`, `number`, `city`…).
3. **Entrada**: [`POST /api/products`](/api/referencia/products/post-communities-by-community-id-products) con `type: "ONE_TIME"`, `price`, `hasStock: true` y `stockQuantity`. Después, [publícala](/api/referencia/products/post-communities-by-community-id-products-by-id-publish).
4. **Abrir el espacio a quien compró**: [`PUT /api/spaces/{id}`](/api/referencia/sections-spaces/put-spaces-by-id) con `visibility: "private"` y `access: { "productIds": [<id de la entrada>] }`.
5. **Aviso fijado**: [`POST /api/content`](/api/referencia/content/post-content) en el espacio del Feed, y [`PUT /api/feed/{type}/{id}/pin`](/api/referencia/feed/put-feed-by-type-by-id-pin) con el id de la publicación.

## Plan con adicionales

1. **Opciones de cobro del plan**: un [`POST .../products`](/api/referencia/products/post-communities-by-community-id-products) por opción (Mensual, Anual), `type: "SUBSCRIPTION"`.
2. **El adicional**: otro `POST .../products`, `type: "SUBSCRIPTION"`, `billingInterval: "MONTHLY"`. **No** entra en los `productIds` de ningún plan.
3. **Plan**: [`POST .../subscription-groups`](/api/referencia/subscriptions/post-communities-by-community-id-subscription-groups) con los `productIds` del paso 1.
4. **Adicionales en el plan**: [`PUT .../subscription-groups/{id}`](/api/referencia/subscriptions/put-communities-by-community-id-subscription-groups-by-id) con `addOnProductIds: [<id del paso 2>]`.

## Antes de vender: el cobro

Un orden que vale para cualquier venta:

1. [`POST .../business-information`](/api/referencia/business/post-communities-by-community-id-business-information) y [`.../submit`](/api/referencia/business/post-communities-by-community-id-business-information-submit).
2. [`POST .../payout-settings`](/api/referencia/payouts/post-communities-by-community-id-payout-settings) y [`.../submit`](/api/referencia/payouts/post-communities-by-community-id-payout-settings-submit).
3. Esperar las dos aprobaciones (hasta 7 días laborables). [`GET .../payout-settings/prerequisites`](/api/referencia/payouts/get-communities-by-community-id-payout-settings-prerequisites) dice lo que falta.

Los productos, las opciones, los planes, los adicionales, los cupones y las ofertas de downsell se pueden crear y editar antes de la aprobación: el producto nace `DRAFT`, con la moneda del país de la Información Empresarial (en cualquier estado) o `BRL` si no la hay. Publicar ([`POST .../products/{id}/publish`](/api/referencia/products/post-communities-by-community-id-products-by-id-publish), o `PUT .../products/{id}` con `status: ACTIVE`), el checkout y el retiro esperan la aprobación. Una Información Empresarial aprobada que se edita vuelve a `PENDING` y necesita `.../submit` de nuevo; hasta la nueva aprobación, el checkout rechaza los pagos.

## Los errores de quien se salta un paso

Con `Accept-Language: es-ES`, la mayoría de los mensajes llega en español; algunos llegan todavía en inglés o en portugués, y aquí aparecen tal como los devuelve la API.

| Llamada | Faltaba | Respuesta |
|---|---|---|
| `POST /api/spaces` | la sección | `400` · *Seção não encontrada ou não pertence a esta comunidade.* ("Sección no encontrada o no pertenece a esta comunidad") |
| `POST /api/spaces` (o `PUT`) | la sección es más restringida | `400` · *This space cannot be more open than the section "…", which is …* |
| `PUT /api/spaces/{id}` con `access` | el plan, producto o grupo citado | `400` · *The access grant "…" does not exist in this community.* (`param: access`) |
| `POST /api/courses` | el espacio | `400` · *ID do espaço é obrigatório.* o *Espaço não encontrado ou não pertence a esta comunidade.* ("Espacio obligatorio" / "Espacio no encontrado") |
| `POST /api/courses/module` | el curso | `404` · *Course not found* |
| `POST /api/courses/lesson` | el módulo | `404` · *Module not found* |
| `POST .../subscription-groups` | las opciones de cobro | `400` · *Producto no encontrado* |
| `PUT .../subscription-groups/{id}` con `addOnProductIds` | el producto del adicional, o ya es opción de un plan | `400` · *Uno de los complementos no existe en esta comunidad o fue eliminado.* / *Un producto que es opción de cobro de un plan no puede ser complemento de otro.* |
| Configuración del checkout | el cobro aprobado | `400` · *Configuração de pagamento não foi realizada para esta comunidade* ("No se ha configurado el cobro para esta comunidad") |
| `POST .../products/{id}/publish` (o `PUT` con `status: ACTIVE`) | la Información Empresarial aprobada | `403` · *Para publicar y empezar a vender, la comunidad necesita tener la información empresarial aprobada…* |
| `POST .../products/{id}/publish` | el producto en la moneda del país aprobado | `400` · *Este producto está en …, pero la moneda de la información empresarial aprobada es …* (`param: currency`) |
| `POST /api/checkout` | la Información Empresarial aprobada | `403` · *La comunidad debe tener información comercial aprobada para habilitar productos de pago* |
| `POST .../payouts` | saldo para el importe y la comisión | `400` · *Saldo insuficiente. Disponible: …* |
| Cualquiera | la cabecera | `400` · *X-CommunityId é obrigatório* / *Community ID is required* |

Algunas validaciones de formato responden en inglés (como *Valid course ID is required* cuando el id no es un UUID).

## Consejos

- **Guarda cada id** que vuelve en `data.id`: es el que pide la llamada siguiente.
- **Envía el mismo `communityId`** en el cuerpo (cuando la ruta lo pide) y en la cabecera.
- **Repetir no deshace**: si una secuencia se para a medias, continúa desde el paso que falló, en lugar de empezar de nuevo (empezar de nuevo crea duplicados).
- En el [MCP](/mcp/ferramentas), las herramientas compuestas harán este orden por su cuenta.
