MyLook — Arquitectura y API

Plataforma nueva · entorno de revisión
API ok · versión 1.0.0 · entorno staging
commit 72eb053 · esquema 039_commission_standing_single_rule.sql · desplegado 2026-08-11T14:05:25Z
150rutas
177operaciones
73tablas
38migraciones
2565verificaciones automáticas

Explorar la API permite ejecutar cada endpoint desde el navegador y ver la petición, la respuesta y los errores exactos. Nada de esta página está escrito a mano: las rutas se leen del propio documento OpenAPI del servidor y las tablas de la base de datos.

Estado: prototipo en construcción

Lo que verá aquí es un prototipo funcional en un entorno de revisión, construido sobre la arquitectura y las pantallas que usted definió. No es un producto terminado y no debe evaluarse como tal.

Está deliberadamente incompleto, y decirlo por adelantado es parte del trabajo. Lo que aún no está construido, y por qué:

Lo que sí está terminado y comprobable es lo que aparece más abajo: el esquema de datos, la autenticación, los roles y permisos, los negocios y sucursales, los profesionales y los servicios — con las direcciones para comprobarlo usted mismo.

Cómo verificar esto sin creernos nada

Cada afirmación de esta página tiene una dirección que la comprueba. Ábralas, o entrégueselas a quien le asesore técnicamente: devuelven datos del sistema en ejecución, no de un documento.

Debe responder datos reales

Debe NEGARSE y ésa es la prueba

Si estas direcciones devolvieran datos, la plataforma estaría abierta. Devuelven 401 sin sesión y 403 con una sesión que no corresponde.

Una persona, varios negocios su regla

Usted pidió que no existan «Professional 2» ni «Business Owner 2»: una persona debe poder trabajar con varios negocios con una sola cuenta.

La base de datos lo impide, no lo recomienda: professionals.user_id tiene una restricción UNIQUE, por lo que un segundo perfil para la misma persona no puede crearse — ni por error ni a propósito. Contratar a alguien que ya trabaja en otro negocio añade un vínculo de sucursal, nunca una identidad nueva.

Comprobado en ejecución: un negocio contrató a una profesional que ya trabajaba en otro, propiedad de una cuenta distinta, y el perfil devuelto fue el mismo. Los roles son owner, manager, professional y front_desk, y se otorgan POR NEGOCIO.

Foundation lo que usted pidió revisar

Cada sección nombra las tablas que la sostienen y los endpoints que la exponen.

Configuración del proyecto y base de datos Project and database configuration

PostgreSQL 16 · SQLAlchemy 2.0 async · Redis 7 · Docker Compose. El esquema se aplica con migraciones numeradas, cada una en su propia transacción y registrada una sola vez.

2 endpoints
  • GET /
  • GET /health

Autenticación Authentication

Tokens de acceso y de refresco, sesiones por dispositivo, verificación de correo y recuperación de contraseña. Límite de intentos por IP en Redis.

users13user_sessions10user_tokens9
21 endpoints
  • GET /v1/admin/staff/2fa
  • POST /v1/admin/staff/{user_id}/2fa/disable
  • GET /v1/admin/staff/{user_id}/2fa/events
  • POST /v1/auth/forgot-password
  • POST /v1/auth/login
  • POST /v1/auth/logout
  • POST /v1/auth/logout-all
  • POST /v1/auth/refresh
  • POST /v1/auth/register
  • POST /v1/auth/resend-verification
  • POST /v1/auth/reset-password
  • POST /v1/auth/verify-email
  • GET/PATCH /v1/me
  • GET /v1/me/2fa
  • POST /v1/me/2fa/confirm
  • POST /v1/me/2fa/disable
  • POST /v1/me/2fa/recovery-codes
  • POST /v1/me/2fa/start
  • POST /v1/me/2fa/verify
  • GET /v1/me/sessions

Usuarios, roles y permisos Users, roles and permissions

NO existe un rol global por usuario. La autorización se resuelve SIEMPRE por contexto. Los permisos de negocio viven en business_members (owner · manager · professional · front_desk) y se otorgan POR NEGOCIO, de modo que una persona puede trabajar con varios negocios sin duplicar su cuenta: identidad única → negocio → membresía → rol → permiso. El personal de MyLook vive en una tabla aparte (platform_staff), nunca en el perfil del usuario. Puede comprobarse: no hay ninguna columna primary_role en el esquema.

users13platform_staff5business_members14audit_log9verification_events11
23 endpoints
  • GET /v1/admin/businesses
  • GET /v1/admin/businesses/{business_id}/history
  • POST /v1/admin/businesses/{business_id}/hold
  • POST /v1/admin/businesses/{business_id}/reinstate
  • POST /v1/admin/businesses/{business_id}/suspend
  • POST /v1/admin/businesses/{business_id}/unverify
  • POST /v1/admin/businesses/{business_id}/verify
  • GET /v1/admin/directory/claims
  • POST /v1/admin/directory/claims/{claim_id}/approve
  • POST /v1/admin/directory/claims/{claim_id}/reject
  • GET /v1/admin/overview
  • GET /v1/admin/professionals
  • GET /v1/admin/professionals/{professional_id}/history
  • POST /v1/admin/professionals/{professional_id}/unverify
  • POST /v1/admin/professionals/{professional_id}/verify
  • GET /v1/admin/staff/2fa
  • POST /v1/admin/staff/{user_id}/2fa/disable
  • GET /v1/admin/staff/{user_id}/2fa/events
  • GET/POST /v1/businesses/{business_id}/members
  • GET /v1/businesses/{business_id}/my-access
  • GET/PATCH /v1/me

Negocios y sucursales Businesses and branches

Una organización agrupa negocios; cada negocio tiene una o más sucursales con su propio horario y su propia zona horaria. Toda hora se resuelve en la zona de la sucursal.

organizations8businesses15branches17branch_hours5branch_hour_overrides7
28 endpoints
  • GET /v1/admin/businesses
  • GET /v1/admin/businesses/{business_id}/history
  • POST /v1/admin/businesses/{business_id}/hold
  • POST /v1/admin/businesses/{business_id}/reinstate
  • POST /v1/admin/businesses/{business_id}/suspend
  • POST /v1/admin/businesses/{business_id}/unverify
  • POST /v1/admin/businesses/{business_id}/verify
  • GET /v1/admin/overview
  • POST/GET /v1/businesses
  • GET /v1/businesses/mine
  • GET/PATCH /v1/businesses/{business_id}
  • GET/POST /v1/businesses/{business_id}/branches
  • PATCH /v1/businesses/{business_id}/branches/{branch_id}
  • GET/PUT /v1/businesses/{business_id}/branches/{branch_id}/hours
  • GET/POST /v1/businesses/{business_id}/members
  • GET/PATCH/DELETE /v1/businesses/{business_id}/members/{member_id}
  • GET /v1/businesses/{business_id}/members/{member_id}/history
  • POST /v1/businesses/{business_id}/members/{member_id}/reactivate
  • POST /v1/businesses/{business_id}/members/{member_id}/revoke
  • POST /v1/businesses/{business_id}/members/{member_id}/suspend
  • GET /v1/businesses/{business_id}/my-access

Profesionales Professionals

El perfil pertenece a la PERSONA: professionals.user_id es UNIQUE en la base de datos, por lo que un profesional que trabaja en varios negocios tiene un solo perfil. La tabla NO tiene business_id: se llega a un negocio por professional_branches → branches → businesses, y por eso las rutas cuelgan de /businesses/{business_id}/ — el negocio es el ámbito de permisos, no el dueño de la identidad. Tres modelos de colaboración: independiente, porcentaje de salón y renta de silla. Dos operaciones sobre un profesional pertenecen a otros dominios y aparecen allí: las habilidades (professional_services) en Servicios, y el horario (availability_rules) en Reservas.

professionals13professional_branches7compensation_agreements17chair_rent_cycles10chair_rent_collections5
12 endpoints
  • GET /v1/admin/professionals
  • GET /v1/admin/professionals/{professional_id}/history
  • POST /v1/admin/professionals/{professional_id}/unverify
  • POST /v1/admin/professionals/{professional_id}/verify
  • GET/POST /v1/businesses/{business_id}/professionals
  • GET/PATCH /v1/businesses/{business_id}/professionals/{professional_id}
  • POST/GET /v1/businesses/{business_id}/professionals/{professional_id}/agreements
  • GET /v1/businesses/{business_id}/professionals/{professional_id}/rent-cycles
  • GET /v1/professionals

Servicios Services

Precio y duración se congelan en la cita al reservar, de modo que un cambio de precio no altera una cita ya acordada. professional_services —qué sabe hacer cada profesional— vive aquí: es el catálogo el que dice qué servicios existen y quién puede prestarlos.

services14service_options7branch_services5professional_services6categories9
19 endpoints
  • PUT /v1/businesses/{business_id}/branches/{branch_id}/services/{service_id}
  • GET /v1/businesses/{business_id}/branches/{branch_id}/services/{service_id}/price
  • GET/POST /v1/businesses/{business_id}/membership-plans
  • GET /v1/businesses/{business_id}/membership-plans/manage
  • PATCH/DELETE /v1/businesses/{business_id}/membership-plans/{plan_id}
  • POST /v1/businesses/{business_id}/memberships
  • GET/POST /v1/businesses/{business_id}/products
  • DELETE /v1/businesses/{business_id}/products/{product_id}
  • POST/GET /v1/businesses/{business_id}/professionals/{professional_id}/skills
  • GET/POST /v1/businesses/{business_id}/services
  • PATCH /v1/businesses/{business_id}/services/{service_id}
  • GET /v1/catalog/categories
  • GET /v1/catalog/discovery/distinguished-businesses
  • GET /v1/catalog/discovery/popular-services

El resto de la plataforma

Reservas y agenda

appointments23appointment_events7availability_rules7time_blocks8waitlist_entries10
14 endpoints
  • POST /v1/booking/appointments
  • GET /v1/booking/appointments/mine
  • GET /v1/booking/appointments/{appointment_id}
  • PATCH /v1/booking/appointments/{appointment_id}/cancel
  • POST /v1/booking/appointments/{appointment_id}/checkout
  • PATCH /v1/booking/appointments/{appointment_id}/reschedule
  • PATCH /v1/booking/appointments/{appointment_id}/status
  • GET /v1/booking/availability
  • PUT/GET /v1/booking/professionals/{professional_id}/availability
  • POST /v1/booking/time-blocks
  • GET /v1/businesses/{business_id}/branches/{branch_id}/agenda
  • GET/PUT /v1/businesses/{business_id}/branches/{branch_id}/hours

Dinero

payments20payment_lines7ledger_entries11refunds20payouts12wallet_movements6money_settings10
21 endpoints
  • GET /v1/businesses/{business_id}/earnings
  • GET /v1/businesses/{business_id}/payouts
  • GET/POST /v1/businesses/{business_id}/payouts/account
  • POST /v1/businesses/{business_id}/payouts/account/link
  • GET /v1/money/disputes
  • POST /v1/money/disputes/{dispute_id}/accept-liability
  • GET /v1/money/disputes/{dispute_id}/liability
  • GET /v1/money/earnings/mine
  • GET /v1/money/owed/mine
  • POST /v1/money/payments/{payment_id}/refund
  • GET /v1/money/payments/{payment_id}/refund-preview
  • GET /v1/money/payments/{payment_id}/refunds
  • GET /v1/money/payouts/mine
  • GET /v1/money/penalties/held
  • POST /v1/money/quote
  • GET /v1/money/receipts/{payment_id}
  • GET /v1/money/wallet
  • GET /v1/money/wallet/movements
  • GET /v1/money/webhooks/events
  • POST /v1/webhooks/stripe

Membresías y suscripciones

plans15subscriptions12
14 endpoints
  • GET/POST /v1/businesses/{business_id}/membership-plans
  • GET /v1/businesses/{business_id}/membership-plans/manage
  • PATCH/DELETE /v1/businesses/{business_id}/membership-plans/{plan_id}
  • POST /v1/businesses/{business_id}/memberships
  • GET /v1/me/membership
  • GET /v1/me/memberships
  • GET /v1/me/subscription
  • GET /v1/plans
  • POST /v1/subscriptions
  • GET/DELETE /v1/subscriptions/{subscription_id}
  • POST /v1/subscriptions/{subscription_id}/cancel

Tienda

products11carts8cart_items6product_orders22product_order_items10branch_inventory5
13 endpoints
  • GET /v1/businesses/{business_id}/orders
  • GET/PATCH /v1/businesses/{business_id}/orders/{order_id}
  • GET /v1/cart
  • POST /v1/cart/items
  • PATCH/DELETE /v1/cart/items/{item_id}
  • GET/DELETE /v1/cart/{cart_id}
  • POST /v1/cart/{cart_id}/checkout
  • GET /v1/orders/mine
  • GET /v1/orders/{order_id}
  • GET /v1/products

Reseñas y comunidad

reviews15review_responses6favorites5referrals10conversations8messages7notifications13device_tokens6
18 endpoints
  • GET /v1/businesses/{business_id}/rating
  • GET /v1/businesses/{business_id}/reviews
  • POST /v1/conversations
  • GET /v1/conversations/mine
  • GET/POST /v1/conversations/{conversation_id}/messages
  • POST /v1/device-tokens
  • GET/POST /v1/favorites
  • DELETE /v1/favorites/{kind}/{target_id}
  • GET /v1/notifications
  • POST /v1/notifications/read-all
  • POST /v1/notifications/{notification_id}/read
  • POST /v1/referrals
  • GET /v1/referrals/mine
  • POST /v1/reviews
  • GET /v1/reviews/mine
  • POST /v1/reviews/{review_id}/respond

Directorio

directory_listings22directory_claims16claim_evidence7
7 endpoints
  • GET /v1/admin/directory/claims
  • POST /v1/admin/directory/claims/{claim_id}/approve
  • POST /v1/admin/directory/claims/{claim_id}/reject
  • POST /v1/directory/ingest
  • GET /v1/directory/search
  • GET /v1/directory/{listing_id}
  • POST /v1/directory/{listing_id}/claim

Promociones

promotions23promotion_services3promotion_redemptions7
8 endpoints
  • GET/POST /v1/businesses/{business_id}/promotions
  • GET /v1/businesses/{business_id}/promotions/manage
  • PATCH/DELETE /v1/businesses/{business_id}/promotions/{promotion_id}
  • GET /v1/promotions
  • GET /v1/promotions/{promotion_id}
  • POST /v1/promotions/{promotion_id}/quote

Medios

media_assets9
4 endpoints
  • GET /v1/businesses/{business_id}/media
  • POST /v1/media
  • GET/DELETE /v1/media/{key}

Superficie por dominio

26organization
21identity
21money
19catalog
18admin
18engagement
14memberships
14booking
13shop
12professionals
8promotions
7directory
4billing
4media
2discovery
2system
1webhooks

Verificación automática

2565 comprobaciones se ejecutan contra la plataforma antes de cada entrega, y deben pasar todas. No son pruebas de código aisladas: cada una llama a la API real —crear un negocio, reservar, cobrar, repartir el dinero, negar un acceso— y comprueba la respuesta.

De ésas, 1218 pueden ejecutarse contra este mismo entorno de revisión a través de HTTP. Las restantes leen la base de datos directamente, que un despliegue no expone, y por eso se ejecutan aparte en lugar de omitirse en silencio.

La suite falla también cuando una comprobación se omite. Una prueba que se salta porque falta una variable de entorno es una luz verde con la bombilla quitada.

Cómo se aplica el esquema

38 migraciones numeradas. Cada una se ejecuta una sola vez, dentro de su propia transacción, y queda registrada en schema_migrations. Un archivo modificado después de haberse aplicado detiene el despliegue: la base de datos y el repositorio no pueden discrepar en silencio.

001_identity.sql002_organization.sql003_professionals.sql004_catalog.sql005_booking.sql006_money.sql007_engagement.sql008_directory.sql009_seed_taxonomy.sql010_media.sql011_branch_cover.sql012_account_recovery.sql013_notification_delivery.sql014_ledger_beneficiary_consistency.sql015_seed_plans.sql016_promotions.sql017_commerce.sql018_service_stats.sql019_verification.sql020_connect.sql021_membership_lifecycle.sql022_subscription_domains.sql023_ledger_immutable.sql024_refunds.sql025_admin_2fa.sql026_owner_decisions_v1.sql027_reconcile_fee_distribution.sql028_drop_cleanup_scratch.sql029_business_memberships.sql030_owner_decisions_v2.sql031_penalty_backfill_to_professional.sql033_membership_scope.sql034_financial_rules_registry.sql035_tax_engine.sql036_dispute_liability.sql037_owner_decisions_v3.sql038_commission_chargeback_reversal.sql039_commission_standing_single_rule.sql