Visión general
La API MaIA es el gateway HTTPS que B4A expone en maiascan.ai para los productos MaIA basados en foto. Te autenticas con una clave de tu cuenta, envías una foto en multipart/form-data y recibes la respuesta de forma síncrona: un perfil de belleza en JSON (MaIA Scan — tono y subtono de piel, color y tipo de cabello, eligiendo qué modelos ejecutar) o la misma foto en PNG con el producto aplicado (MaIA Try-On — labial en tonos de demostración o en cualquier color de tu marca, y base como simulador de maquillaje). Los modelos son experimentales: la respuesta trae un estado por atributo y señala cuándo la persona debe confirmar el resultado.
No se asume nada de tu stack: cualquier cliente HTTP capaz de enviar multipart funciona. No hay SDK obligatorio, webhook ni estado de sesión — la respuesta de la llamada es el resultado. El análisis es cosmético y basado en foto: no es diagnóstico, no hace reconocimiento facial y no identifica personas.
| Producto | Disponibilidad | Endpoint | Descripción |
|---|---|---|---|
| MaIA Scan | Self-service vía API | POST /api/v1/scan | Perfil de piel y cabello en JSON a partir de una selfie frontal (foto lateral opcional): tono y subtono de piel, color y tipo de cabello. Eliges qué modelos ejecutar en el campo models. |
| MaIA Try-On — labial | Self-service vía API | POST /api/v1/try-on | La foto de la cliente vuelve en PNG con el labial aplicado: seis tonos de demostración (shade) o cualquier color de tu marca en #RRGGBB (color), con acabado matte, satin o gloss e intensidad ajustable. |
| MaIA Try-On — base (simulador de maquillaje) | Self-service vía API | POST /api/v1/try-on | category=foundation: la misma foto con una base del color que indiques (#RRGGBB), con intensidad ajustable. Mismo endpoint, misma clave. |
| MaIA Beauty Advisor | Bajo proyecto | — | No es un endpoint self-service. B4A lo entrega como proyecto — en el WhatsApp de la marca, como widget en la página de producto o en el chat — usando los mismos datos de perfil que devuelve MaIA Scan y el catálogo integrado de tu marca. |
Precios
Compras créditos en paquetes y los usas en el scan y en la prueba virtual. Los créditos no caducan. Los precios de abajo están en dólares para empresas fuera de Brasil, con tarjeta; las empresas brasileñas pagan en reales (R$ 1.998, R$ 4.998 y R$ 24.998) con tarjeta, Pix o boleto en nuestro checkout.
| Paquete | Precio | Créditos | Por crédito |
|---|---|---|---|
| Starter | US$ 398 | 2.500 | US$ 0,16 |
| Growth | US$ 998 | 10.000 | US$ 0,10 |
| Scale | US$ 4.998 | 60.000 | US$ 0,08 |
Las recargas puntuales y automáticas siguen el precio por crédito de tu último paquete pagado. Volúmenes enterprise: habla con nosotros.
Cuántos créditos cuesta cada operación está en el área de la cuenta y en la documentación en PDF, disponibles para cualquier login — incluso antes de la primera compra.
Empieza en cuatro pasos
Crea la cuenta
Entra con Google, e-mail y contraseña o recibe un enlace mágico por e-mail. No hay aprobación manual — y la documentación completa en PDF, con la lista de precios, ya queda disponible en tu cuenta.
Crear cuentaCompra un paquete de créditos
Starter (2.500 créditos), Growth (10.000) o Scale (60.000) — con tarjeta en dólares, o en reales con tarjeta, Pix o boleto para empresas brasileñas. Los créditos no caducan.
Ver paquetesCrea la clave de API
La creación de claves se habilita tras la primera compra. La clave (msk_live_…) aparece una única vez — cópiala y guárdala en tu gestor de secretos.
Mi cuentaHaz la primera llamada
Envía una selfie a POST /api/v1/scan (eligiendo los modelos en models) o una foto con shade/color, finish e intensity a POST /api/v1/try-on. La respuesta llega en la misma solicitud.
curl -X POST https://maiascan.ai/api/v1/scan \
-H "Authorization: Bearer msk_live_…" \
-H "x-request-id: order-8841" \
-F "front=@selfie.jpg;type=image/jpeg" \
-F "side=@profile.jpg;type=image/jpeg" \
-F "models=skin,hair_color,hair_type"
# models is optional: omit it for the complete scan, or send e.g. "models=skin"Autenticación
Toda ruta en /api/v1 exige el header Authorization con una clave de API en formato Bearer. La clave identifica la cuenta (y, por tanto, el saldo de créditos) y la propia clave usada — el uso queda registrado por clave. Tu clave nunca sale del gateway: las llamadas al modelo se hacen con la credencial de B4A, en nombre de tu cuenta.
Authorization: Bearer msk_live_…- Formato: msk_live_ seguido de 32 caracteres alfanuméricos. Guardamos solo el hash SHA-256 y un prefijo de visualización; el texto completo se muestra una única vez al crearla.
- Hasta 10 claves activas por cuenta. Revoca cualquier clave en cualquier momento en el portal (Mi cuenta → Claves de API); la revocación aplica en la siguiente llamada.
- Clave ausente, inválida o revocada: 401 con { "error": "invalid_api_key" }.
- Usa la clave solo en el servidor. Nunca la incluyas en código de navegador o app distribuida — quien tenga la clave gasta tus créditos.
- Header opcional x-end-user-id (hasta 160 caracteres: letras, números y @ . _ : + -): el identificador de tu cliente final, reenviado al modelo para tu propia conciliación. Fuera de ese formato se ignora, nunca se rechaza.
Créditos
Los créditos se consumen por operación: un análisis MaIA Scan cobra por los modelos que elegiste ejecutar (y solo por los que devolvieron un valor), y cada imagen renderizada por MaIA Try-On — labial o base — cobra su operación. El crédito se reserva antes de llamar al modelo y se liquida cuando llega la respuesta; si el modelo falla, o si un modelo del scan no consigue predecir nada, la parte correspondiente se devuelve automáticamente. Nunca pagas por un resultado que no recibiste, y nosotros nunca procesamos una foto que no podemos cobrar.
- El saldo tras la llamada viene en toda respuesta exitosa: campos credits_charged y credits_remaining en el JSON del scan y headers X-Credits-Charged y X-Credits-Remaining en ambos endpoints.
- Saldo insuficiente: la llamada se rechaza antes de cualquier procesamiento con 402 y { "error": "insufficient_credits", "balance": 2, "required": 3 }. El intento queda registrado en tu uso, sin cobro.
- Recarga automática: en el portal defines un umbral y un importe; cuando el saldo baja de él, creamos un pedido y enviamos el enlace de pago por e-mail (nunca cobramos la tarjeta sin ti).
Lista de precios y documentación en PDF
La tabla de créditos por operación y el PDF con toda esta documentación — incluidos los vocabularios de los atributos y ejemplos listos — están en tu cuenta, sin compra previa.
POST/api/v1/scan
Envía una selfie frontal (y, si quieres, una foto lateral) y recibe el perfil de belleza de la persona en JSON: tono y subtono de piel, color y tipo de cabello — solo los modelos que pidas. Síncrono: la respuesta es el resultado.
Solicitud
Cuerpo multipart/form-data con los campos de abajo (los campos de texto desconocidos se rechazan con 400). Headers: Authorization (obligatorio), x-request-id y x-end-user-id (opcionales).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
front | archivo | sí | Foto frontal del rostro. Content-Type image/jpeg o image/png (también verificamos los bytes). Hasta 6 MiB. Lado menor recomendado de 480 px o más — por debajo el modelo puede abstenerse. |
side | archivo | opcional | Foto lateral de la misma persona, mismos tipos y límite. Enviada en la misma llamada, sin coste adicional; ayuda a los modelos de cabello. |
models | texto | opcional | Qué modelos ejecutar, separados por coma: skin, hair_color, hair_type (cualquier combinación, sin repetir). Omitido = el análisis completo, con los tres. Valor desconocido: 422 invalid_selection, nada cobrado. |
x-request-id | header | opcional | Tu identificador de la solicitud (hasta 80 caracteres). Se guarda junto al evento de uso para conciliación; no deduplica llamadas. |
x-end-user-id | header | opcional | Identificador de tu cliente final (hasta 160 caracteres, sin espacios), reenviado al modelo. Fuera del formato, se ignora. |
Modelos y atributos
Cada modelo devuelve uno o dos atributos. El campo models acepta los ids de la primera columna; la respuesta trae, en result.attributes, exactamente los atributos de los modelos pedidos.
| Modelo | Descripción | Atributo |
|---|---|---|
skin | Piel — Tono de piel en nueve niveles (very_light … deep) y subtono (cool, neutral, warm). | skin_tone, skin_undertone |
hair_color | Color del cabello — Nueve categorías, de black a light_blonde, más red, gray_white y other. | hair_color |
hair_type | Tipo de cabello — Patrón del cabello: straight, wavy, curly o coily. | hair_pattern |
Respuesta
200 OK, application/json. El envelope es fijo; result es el documento devuelto por el modelo, reenviado tal cual. Los mismos números vienen en los headers X-Session-Id, X-Request-Id, X-Credits-Charged y X-Credits-Remaining.
| Campo | Tipo | Descripción |
|---|---|---|
session_id | string | Identificador del evento de uso (la sesión cobrada). Guárdalo para soporte y conciliación. |
request_id | string | Identificador de la solicitud en el servicio MaIA. Cita los dos ids al hablar con soporte. |
credits_charged | integer | Créditos efectivamente cobrados en esta llamada — los modelos que devolvieron al menos un atributo predicho. |
credits_remaining | integer | Saldo de la cuenta tras esta llamada. |
models | string[] | Modelos pedidos, en orden canónico (skin, hair_color, hair_type). |
models_delivered | string[] | Modelos que devolvieron al menos un atributo con status predicted — los que se cobraron. |
result.attributes.<atributo> | object | Por atributo pedido: status (predicted, abstained o unsupported), value (el valor del vocabulario), score (softmax no calibrado — no es exactitud), model_version, photo_roles y requires_confirmation. |
result.quality / result.experimental / result.requires_confirmation | object · boolean | Diagnósticos de calidad de la foto por rol (front, side) y las flags del modelo. Los modelos son experimentales: pide confirmación a la persona antes de usar un valor en una decisión de compra. |
HTTP/1.1 200 OK
Content-Type: application/json
X-Session-Id: cmg1x3k9h0001abcd
X-Request-Id: 8f1c2e7a-…
X-Credits-Charged: 3
X-Credits-Remaining: 497
{
"session_id": "cmg1x3k9h0001abcd",
"request_id": "8f1c2e7a-…",
"credits_charged": 3,
"credits_remaining": 497,
"models": ["skin", "hair_color", "hair_type"],
"models_delivered": ["skin", "hair_color", "hair_type"],
"result": {
"attributes": {
"skin_tone": { "status": "predicted", "value": "light_medium", "score": 0.41, "score_kind": "uncalibrated_softmax_not_accuracy", "requires_confirmation": true, "photo_roles": ["front"] },
"skin_undertone": { "status": "predicted", "value": "warm", "score": 0.52, "requires_confirmation": true },
"hair_color": { "status": "predicted", "value": "dark_brown", "score": 0.63, "requires_confirmation": true },
"hair_pattern": { "status": "abstained" }
},
"quality": { "front": { … } },
"requires_confirmation": true,
"experimental": true
}
}Estado de cada atributo
Un 200 puede contener abstenciones. Solo se cobra lo que fue predicho:
| Estado | Significado |
|---|---|
predicted | El modelo devolvió un valor del vocabulario (value) con su score. El modelo correspondiente se cobra. |
abstained | El modelo no tuvo confianza suficiente en esta foto (iluminación, encuadre, resolución). No se cobra. |
unsupported | El atributo no puede evaluarse en esta foto (por ejemplo, cabello cubierto). No se cobra. |
Errores
| Estado | Código | Significado | ¿Crédito cobrado? |
|---|---|---|---|
400 | front_required | No se envió el campo front. | no |
400 | — | Campo de texto desconocido (validación del cuerpo). | no |
401 | invalid_api_key | Clave ausente, inválida o revocada. | no |
402 | insufficient_credits | Saldo menor que el necesario para los modelos pedidos; el cuerpo trae balance y required. | no |
413 | photo_too_large | Imagen mayor que 6 MiB. Las subidas muy por encima del límite se cortan en la recepción con un 413 genérico. | no |
415 | unsupported_media_type | Content-Type de uno de los archivos distinto de image/jpeg e image/png. | no |
422 | unsupported_photo | Los bytes no son JPEG ni PNG (o el archivo está vacío). | no |
422 | invalid_selection | models contiene un id desconocido. | no |
422 | bad_photo | El modelo rechazó la foto (rostro no detectado, foto demasiado pequeña). Créditos devueltos. | no |
422 | unusable_photo | Ningún atributo pudo predecirse (todos abstained o unsupported). Todo devuelto; el cuerpo trae session_id y request_id. | no |
429 | rate_limited | Más de 20 solicitudes por minuto con la misma clave (o el servicio está en el límite). Header Retry-After en segundos. | no |
503 | upstream_unavailable | El modelo no respondió (fallo o 180 s de espera). Créditos devueltos; el cuerpo trae session_id. | no |
503 | upstream_not_configured | El servicio de análisis no está conectado en este entorno. No se cobra nada. | no |
Límites
- Hasta 6 MiB por archivo, como máximo 2 archivos (front + side), JPEG o PNG estáticos.
- Llamada síncrona; el gateway espera al modelo hasta 180 s. Configura tu cliente HTTP con al menos 200 s.
- 20 solicitudes por minuto por clave de API y 120 por minuto por IP de origen.
Consentimiento obligatorio: obtén la autorización explícita de la persona antes de enviar la foto (LGPD). MaIA Scan no hace reconocimiento facial ni identificación; devuelve un análisis cosmético, experimental, para personalización — no es diagnóstico. Los campos con requires_confirmation deben confirmarse con la persona.
Ejemplos
curl -X POST https://maiascan.ai/api/v1/scan \
-H "Authorization: Bearer msk_live_…" \
-H "x-request-id: order-8841" \
-F "front=@selfie.jpg;type=image/jpeg" \
-F "side=@profile.jpg;type=image/jpeg" \
-F "models=skin,hair_color,hair_type"
# models is optional: omit it for the complete scan, or send e.g. "models=skin"POST/api/v1/try-on
Envía una foto frontal con el producto a aplicar y recibe la misma foto en PNG. Labial (category=lipstick, por defecto): un tono de demostración (shade) o cualquier color de tu marca (color, #RRGGBB), con acabado e intensidad. Base (category=foundation): un color #RRGGBB con intensidad. Solo cambia la zona del maquillaje. Síncrono.
Solicitud
Cuerpo multipart/form-data con los campos de abajo (los campos de texto desconocidos se rechazan con 400). Headers: Authorization (obligatorio), x-request-id y x-end-user-id (opcionales).
| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
photo | archivo | sí | Foto frontal, JPEG o PNG (verificamos los bytes, no solo el Content-Type). Hasta 6 MiB; lado menor de al menos 320 px; boca visible para labial. |
category | texto | opcional | lipstick (por defecto) o foundation. |
shade | texto | opcional | Labial: uno de los tonos de demostración — rose, red, berry, coral, plum o nude (ver GET /api/v1/try-on/shades). Exactamente uno entre shade y color. |
color | texto | opcional | Cualquier color en #RRGGBB (mayúsculas o minúsculas). Labial: alternativa a shade, para la paleta de tu marca. Base: obligatorio. |
finish | texto | opcional | Labial: matte (por defecto), satin o gloss. No aplica a la base. |
intensity | texto | opcional | Entero de 0 a 100. Por defecto 100 para labial y 70 para base. |
x-request-id | header | opcional | Tu identificador de la solicitud (hasta 80 caracteres), guardado en el evento de uso. |
El color de tu marca
En lugar de un tono de demostración, envía color=#RRGGBB con el hex de tu producto — el modelo aplica exactamente ese color, con el acabado y la intensidad pedidos. Es el camino para probar tu propia paleta sin proyecto de calibración.
curl -X POST https://maiascan.ai/api/v1/try-on \
-H "Authorization: Bearer msk_live_…" \
-F "photo=@selfie.jpg;type=image/jpeg" \
-F "color=#993355" \
-F "finish=satin" \
-F "intensity=85" \
-o try-on.png
# exactly one of shade / color; X-TryOn-Color echoes the normalised colour (#993355)Base (simulador de maquillaje)
category=foundation aplica una base del color indicado en color, con intensity (por defecto 70). No hay shade ni finish para la base. Misma clave, mismo endpoint, mismo recibo en los headers.
curl -X POST https://maiascan.ai/api/v1/try-on \
-H "Authorization: Bearer msk_live_…" \
-F "photo=@selfie.jpg;type=image/jpeg" \
-F "category=foundation" \
-F "color=#C68642" \
-F "intensity=70" \
-o foundation.png
# no shade / finish for foundation; X-TryOn-Category: foundationRespuesta
200 OK, image/png — el cuerpo es la imagen renderizada. El recibo viene en los headers:
| Header | Descripción |
|---|---|
X-Session-Id | Identificador del evento de uso (la sesión cobrada). |
X-Request-Id | Identificador de la solicitud en el servicio MaIA. |
X-Credits-Charged | Créditos cobrados por esta imagen. |
X-Credits-Remaining | Saldo de la cuenta tras esta llamada. |
X-TryOn-Category | la categoría renderizada: lipstick, foundation, blush, … o full_look. |
X-TryOn-Color | El color aplicado, en #RRGGBB mayúsculas — el hex del tono de demostración o tu color normalizado. |
X-TryOn-Finish | El acabado aplicado (solo labial). No hay fallback: lo que pediste es lo que se aplicó. |
X-Model-Version | Versión del modelo de render, cuando se informa. |
Cache-Control | no-store. La imagen no queda en ningún caché de nuestro lado. |
HTTP/1.1 200 OK
Content-Type: image/png
Cache-Control: no-store
X-Session-Id: cmg1x4p2r0002efgh
X-Request-Id: 2b7d9f10-…
X-Credits-Charged: 1
X-Credits-Remaining: 496
X-TryOn-Category: lipstick
X-TryOn-Color: #B85C75
X-TryOn-Finish: gloss
X-Model-Version: lipstick-custom-srgb-v1
<PNG bytes>Errores
| Estado | Código | Significado | ¿Crédito cobrado? |
|---|---|---|---|
400 | photo_required | No se envió el campo photo. | no |
400 | — | Campo de texto desconocido o fuera de formato (validación del cuerpo). | no |
401 | invalid_api_key | Clave ausente, inválida o revocada. | no |
402 | insufficient_credits | Saldo insuficiente; el cuerpo trae balance y required. | no |
413 | photo_too_large | Foto mayor que 6 MiB. Las subidas muy por encima del límite se cortan en la recepción con un 413 genérico. | no |
422 | invalid_selection | category, shade, color, finish o intensity fuera del contrato (por ejemplo shade y color juntos, color sin #RRGGBB, base sin color). El cuerpo dice cuál. | no |
422 | unsupported_photo | Los bytes no son JPEG ni PNG (o el archivo está vacío). | no |
422 | bad_photo | El modelo rechazó la foto (rostro no frontal, boca no visible, lado menor por debajo de 320 px). Crédito devuelto. | no |
429 | rate_limited | Más de 20 solicitudes por minuto con la misma clave (o el servicio está en el límite). Header Retry-After en segundos. | no |
503 | upstream_unavailable | El servicio de render falló o no respondió en 180 s. Crédito devuelto; inténtalo de nuevo en unos instantes. | no |
503 | upstream_not_configured | El servicio de render no está conectado en este entorno. No se cobra nada. | no |
Límites
- JPEG o PNG, hasta 6 MiB, lado menor ≥ 320 px.
- Llamada síncrona; el gateway espera al modelo hasta 180 s. Configura tu cliente HTTP con al menos 200 s.
- 20 solicitudes por minuto por clave de API y 120 por minuto por IP de origen.
- El color simulado puede diferir del producto real: el render es experimental y trabaja en sRGB a partir del hex indicado. Paleta calibrada con validación humana y otras categorías de maquillaje: bajo proyecto.
Ejemplos — labial con tono de demostración
curl -X POST https://maiascan.ai/api/v1/try-on \
-H "Authorization: Bearer msk_live_…" \
-F "photo=@selfie.jpg;type=image/jpeg" \
-F "shade=rose" \
-F "finish=gloss" \
-F "intensity=90" \
-D headers.txt \
-o try-on.png
# headers.txt now holds X-Session-Id, X-Request-Id, X-Credits-Charged, X-Credits-Remaining, X-TryOn-Color, X-TryOn-FinishGET/api/v1/try-on/shades
Lista lo que acepta POST /api/v1/try-on: los tonos de demostración con su hex de referencia, los acabados, el formato de color personalizado, los rangos de intensidad, las categorías y el límite de subida. No consume crédito.
Respuesta
200 OK, application/json, Cache-Control: private, max-age=3600. Exige la misma clave (401 sin ella).
| Campo | Tipo | Descripción |
|---|---|---|
shades[].id | string | Valor aceptado en el campo shade del try-on. |
shades[].hex | string | Color de referencia del tono (#RRGGBB) para mostrar en tu interfaz. |
finishes | string[] | Valores aceptados en el campo finish (labial). |
custom_color | boolean | true: el campo color acepta cualquier color de tu marca. |
color_format | string | Formato aceptado en color: #RRGGBB. |
intensity | object | Rango y valor por defecto de la intensidad del labial: { min, max, default }. |
foundation_intensity | object | Rango y valor por defecto de la intensidad de la base: { min, max, default }. |
categories | string[] | Valores aceptados en category: lipstick, foundation. |
max_upload_bytes | integer | Límite de subida de la foto en bytes (6 MiB). |
{
"shades": [
{ "id": "rose", "hex": "#B85C75" },
{ "id": "red", "hex": "#B8293D" },
{ "id": "berry", "hex": "#883252" },
{ "id": "coral", "hex": "#D96758" },
{ "id": "plum", "hex": "#703B5B" },
{ "id": "nude", "hex": "#AF786F" }
],
"finishes": ["matte", "satin", "gloss"],
"custom_color": true,
"color_format": "#RRGGBB",
"intensity": { "min": 0, "max": 100, "default": 100 },
"foundation_intensity": { "min": 0, "max": 100, "default": 70 },
"categories": ["lipstick", "foundation"],
"max_upload_bytes": 6291456
}Ejemplos
curl https://maiascan.ai/api/v1/try-on/shades \
-H "Authorization: Bearer msk_live_…"SDK en el navegador (acceso anticipado)
Además de la API por foto, MaIA Try-On existe como SDK para el navegador: trece simuladores (labial, base, rubor, polvo, corrector, sombra, máscara, cejas, delineador, bronceador, contorno, iluminador y delineador de labios) y un Full Look, en vivo con la cámara o desde una foto, renderizados localmente en el dispositivo de la clienta. No se sube ninguna imagen; tu marca aloja el paquete inmutable en su propio origen.
El SDK nunca llama a esta API por su cuenta. Labial y base pueden recibir un render final en el servidor — por el endpoint de arriba, con la clave de la cuenta del lado del servidor — cobrado en créditos, como cualquier llamada; los demás productos y el Full Look son vistas previas locales. La guía de integración (JavaScript, React, Angular, CSP, privacidad, versiones) está en el área con sesión y el acceso se habilita cuenta por cuenta.
Cómo obtener el SDK hoy
- Crea una cuenta en maiascan.ai (e-mail o Google) y entra en Mi cuenta → SDK.
- Haz clic en "Pedir acceso": el SDK está en acceso anticipado y el equipo B4A lo habilita cuenta por cuenta.
- Con el acceso habilitado, la misma página muestra la versión actual, su SHA-256 y el botón "Descargar paquete" (package.tgz). Aloja el contenido de package/ en tu origen en /vendor/maia-try-on/<versión>/ — el SDK exige el mismo origen para workers, WASM y modelos.
- npm: con el acceso habilitado, npm i @maiascan/try-on funciona a través de nuestro registro privado (maiascan.ai/api/npm), autenticado con la clave de API de la cuenta; las dos líneas del .npmrc están en el área con sesión. No se necesita cuenta en npmjs.com.
Referencia: vocabularios de los atributos
Los valores posibles de value en result.attributes, por atributo. Los vocabularios son fijos por versión de la API (api_version en el envelope del modelo); los valores nuevos llegan como cambio compatible.
| Atributo | Valores posibles | Descripción |
|---|---|---|
skin_tone | very_light, light, light_medium, medium, medium_tan, medium_dark, dark, very_dark, deep | Nueve niveles de tono de piel, del más claro al más profundo. |
skin_undertone | cool, neutral, warm | Subtono de la piel. |
hair_color | black, dark_brown, medium_brown, light_brown, dark_blonde, light_blonde, red, gray_white, other | Color predominante del cabello. |
hair_pattern | straight, wavy, curly, coily | Patrón del cabello. |
Cada atributo viene con status predicted, abstained o unsupported; score es un softmax no calibrado — trátalo como orden de preferencia, no como probabilidad ni exactitud.
Errores y códigos de estado
Todo error es JSON con un campo error estable (para tu código) y un message legible (para el log). Compara error, no message. Ningún error consume crédito: cuando el fallo ocurre después de la reserva (422 bad_photo o unusable_photo, 429, 503), la devolución se registra en la misma transacción y el cuerpo trae session_id.
| Estado | Significado |
|---|---|
400 | Solicitud mal formada: campo obligatorio ausente o campo de texto desconocido. |
401 | invalid_api_key — clave ausente, inválida o revocada. |
402 | insufficient_credits — saldo menor que el necesario; el cuerpo trae balance y required. |
413 | photo_too_large — imagen mayor que 6 MiB. |
415 | unsupported_media_type — Content-Type distinto de image/jpeg e image/png (scan). |
422 | Entrada válida en forma, inválida en contenido: invalid_selection, unsupported_photo, bad_photo, unusable_photo (scan). |
429 | rate_limited — límite por clave o del servicio; espera Retry-After segundos y reintenta con backoff. |
503 | upstream_unavailable (crédito devuelto) o upstream_not_configured (nada cobrado). |
HTTP/1.1 402 Payment Required
Content-Type: application/json
{
"error": "insufficient_credits",
"message": "Buy a credit package to continue.",
"balance": 2,
"required": 3
}Límites, idempotencia y x-request-id
- Rate limit: 20 solicitudes por minuto por clave de API en todas las rutas /api/v1 (429 rate_limited con Retry-After), además de 120 por minuto por IP de origen. Para volúmenes mayores, habla con nosotros.
- Idempotencia: las llamadas no son idempotentes — cada 200 consume créditos. No repitas automáticamente una llamada que devolvió 200; repite solo los errores 429 y 503 (que no cobran), respetando Retry-After y con backoff exponencial.
- x-request-id: envía tu identificador (hasta 80 caracteres). Se guarda en el evento de uso y aparece en la conciliación; úsalo con session_id / X-Session-Id y request_id / X-Request-Id al hablar con soporte.
- Timeouts: el gateway espera al modelo hasta 180 s. Configura tu cliente HTTP con al menos 200 s para no abandonar una llamada que aún será cobrada y respondida.
Tratamiento de datos y consentimiento
- Consentimiento: eres responsable de obtener la autorización explícita de la persona antes de enviar cualquier foto, según la LGPD. En nuestra propia demo el texto usado es: "Autorizo el procesamiento de esta foto solo para generar la simulación; no se almacena."
- Fotos en el gateway: permanecen en memoria solo durante la solicitud y se reenvían una vez al modelo. El gateway no graba fotos en disco, base de datos ni logs — los logs registran tamaño, operación, latencia, estado e identificadores de solicitud.
- En el servicio MaIA: nada se retiene ni se usa para entrenar (retained: false, used_for_training: false en el envelope). Solo el resultado — JSON o PNG — vuelve a ti, con Cache-Control: no-store.
- Lo que no hacemos: reconocimiento facial, identificación de personas, inferencia de rasgos protegidos ni diagnóstico médico. El análisis es cosmético y experimental; los campos con requires_confirmation deben confirmarse con la persona.
- Registro de uso: por solicitud guardamos cuenta, clave, endpoint, estado, créditos, latencia, x-request-id y el request_id del modelo — es lo que aparece en tu página de uso.
Base URL, versión y contacto
https://maiascan.ai/api- Base URL: https://maiascan.ai/api — siempre HTTPS. Las rutas públicas están bajo /v1.
- Versionado: la versión va en la ruta (v1). Los cambios compatibles (campos nuevos en el JSON, headers nuevos, tonos nuevos, valores nuevos en los vocabularios) llegan sin cambio de versión; cualquier cambio incompatible nace como /v2, con /v1 mantenida en paralelo durante un periodo anunciado.
- Estado del gateway: GET https://maiascan.ai/api/health devuelve { "status": "ok", "commit": "…" } — sin autenticación.
- Soporte técnico y comercial: comercial@b4a.ai.
¿Necesitas más volumen, límites mayores por clave, paleta calibrada con validación humana, otras categorías de maquillaje, MaIA Beauty Advisor o un contrato enterprise? Habla con nosotros — B4A entrega proyectos completos sobre la misma API.