Visão geral
A API MaIA é o gateway HTTPS que a B4A expõe em maiascan.ai para os produtos MaIA baseados em foto. Você autentica com uma chave da sua conta, envia uma foto em multipart/form-data e recebe a resposta de forma síncrona: um perfil de beleza em JSON (MaIA Scan — tom e subtom de pele, cor e tipo de cabelo, escolhendo quais modelos rodar) ou a mesma foto em PNG com o produto aplicado (MaIA Try-On — batom em tons de demonstração ou em qualquer cor da sua marca, e base como simulador de maquiagem). Os modelos são experimentais: a resposta traz um status por atributo e sinaliza quando a pessoa deve confirmar o resultado.
Nada é assumido do lado da sua stack: qualquer cliente HTTP capaz de enviar multipart funciona. Não há SDK obrigatório, webhook nem estado de sessão — a resposta da chamada é o resultado. A análise é cosmética e baseada em foto: não é diagnóstico, não faz reconhecimento facial e não identifica pessoas.
| Produto | Disponibilidade | Endpoint | Descrição |
|---|---|---|---|
| MaIA Scan | Self-service via API | POST /api/v1/scan | Perfil de pele e cabelo em JSON a partir de uma selfie frontal (foto de perfil opcional): tom e subtom de pele, cor e tipo de cabelo. Você escolhe quais modelos rodar no campo models. |
| MaIA Try-On — batom | Self-service via API | POST /api/v1/try-on | A foto da cliente volta em PNG com o batom aplicado: seis tons de demonstração (shade) ou qualquer cor da sua marca em #RRGGBB (color), com acabamento matte, satin ou gloss e intensidade ajustável. |
| MaIA Try-On — base (simulador de maquiagem) | Self-service via API | POST /api/v1/try-on | category=foundation: a mesma foto com uma base na cor que você informar (#RRGGBB), com intensidade ajustável. Mesmo endpoint, mesma chave. |
| MaIA Beauty Advisor | Sob projeto | — | Não é um endpoint self-service. É entregue pela B4A como projeto — no WhatsApp da marca, como widget na página de produto ou no chat — usando os mesmos dados de perfil que a MaIA Scan devolve e o catálogo integrado da sua marca. |
Preços
Você compra créditos em pacotes — por cartão, Pix ou boleto, no nosso checkout — e usa no scan e na prova virtual. Créditos não expiram. Empresas fora do Brasil pagam em dólar, por cartão: US$ 398, US$ 998 e US$ 4.998.
| Pacote | Preço | Créditos | Por crédito |
|---|---|---|---|
| Starter | R$ 1.998 | 2.500 | R$ 0,80 |
| Growth | R$ 4.998 | 10.000 | R$ 0,50 |
| Scale | R$ 24.998 | 60.000 | R$ 0,42 |
Recargas avulsas e automáticas seguem o preço por crédito do seu último pacote pago. Volumes enterprise: fale com a gente.
Quantos créditos custa cada operação está na área da conta e na documentação em PDF, disponíveis para qualquer login — antes mesmo da primeira compra.
Comece em quatro passos
Crie a conta
Entre com Google, e-mail e senha ou receba um link mágico por e-mail. Não há aprovação manual — e a documentação completa em PDF, com a lista de preços, já fica disponível na sua conta.
Criar contaCompre um pacote de créditos
Starter (2.500 créditos), Growth (10.000) ou Scale (60.000) — pagamento por cartão, Pix ou boleto no nosso próprio checkout. Os créditos não expiram.
Ver pacotesCrie a chave de API
A criação de chaves é liberada após a primeira compra. A chave (msk_live_…) aparece uma única vez — copie e guarde no seu cofre de segredos.
Minha contaFaça a primeira chamada
Envie uma selfie para POST /api/v1/scan (escolhendo os modelos em models) ou uma foto com shade/color, finish e intensity para POST /api/v1/try-on. A resposta chega na mesma requisição.
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"Autenticação
Toda rota em /api/v1 exige o header Authorization com uma chave de API no formato Bearer. A chave identifica a conta (e, portanto, o saldo de créditos) e a própria chave usada — o uso fica registrado por chave. A sua chave nunca sai do gateway: as chamadas ao modelo são feitas com a credencial da B4A, em nome da sua conta.
Authorization: Bearer msk_live_…- Formato: msk_live_ seguido de 32 caracteres alfanuméricos. Guardamos apenas o hash SHA-256 e um prefixo de exibição; o texto completo é mostrado uma única vez na criação.
- Até 10 chaves ativas por conta. Revogue qualquer chave a qualquer momento no portal (Minha conta → Chaves de API); a revogação vale na chamada seguinte.
- Chave ausente, inválida ou revogada: 401 com { "error": "invalid_api_key" }.
- Use a chave apenas no servidor. Nunca a embuta em código de navegador ou app distribuído — quem tiver a chave gasta os seus créditos.
- Header opcional x-end-user-id (até 160 caracteres: letras, números e @ . _ : + -): o identificador da sua cliente final, repassado ao modelo para a sua própria conciliação. Fora desse formato ele é ignorado, nunca recusado.
Créditos
Os créditos são consumidos por operação: uma análise MaIA Scan cobra pelos modelos que você escolheu rodar (e só pelos que devolveram um valor), e cada imagem renderizada pelo MaIA Try-On — batom ou base — cobra a sua operação. O crédito é reservado antes de chamarmos o modelo e liquidado quando a resposta chega; se o modelo falhar, ou se um modelo do scan não conseguir prever nada, a parte correspondente é devolvida automaticamente. Você nunca paga por um resultado que não recebeu, e nós nunca processamos uma foto que não podemos cobrar.
- O saldo após a chamada vem em toda resposta bem-sucedida: campos credits_charged e credits_remaining no JSON do scan e headers X-Credits-Charged e X-Credits-Remaining em ambos os endpoints.
- Saldo insuficiente: a chamada é recusada antes de qualquer processamento com 402 e { "error": "insufficient_credits", "balance": 2, "required": 3 }. A tentativa fica registrada no seu uso, sem cobrança.
- Recarga automática: no portal você define um limiar e um valor; quando o saldo cai abaixo dele, criamos um pedido e enviamos o link de pagamento por e-mail (nunca cobramos o cartão sem você).
Lista de preços e documentação em PDF
A tabela de créditos por operação e o PDF com toda esta documentação — incluindo os vocabulários dos atributos e exemplos prontos — ficam na sua conta, sem compra prévia.
POST/api/v1/scan
Envia uma selfie frontal (e opcionalmente uma foto de perfil) e recebe o perfil de beleza da pessoa em JSON: tom e subtom de pele, cor e tipo de cabelo — só os modelos que você pedir. Síncrono: a resposta é o resultado.
Requisição
Corpo multipart/form-data com os campos abaixo (campos de texto desconhecidos são recusados com 400). Headers: Authorization (obrigatório), x-request-id e x-end-user-id (opcionais).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
front | arquivo | sim | Foto frontal do rosto. Content-Type image/jpeg ou image/png (verificamos também os bytes). Até 6 MiB. Lado menor recomendado de 480 px ou mais — abaixo disso o modelo pode se abster. |
side | arquivo | opcional | Foto de perfil (lateral) da mesma pessoa, mesmos tipos e limite. Enviada na mesma chamada, sem custo adicional; ajuda os modelos de cabelo. |
models | texto | opcional | Quais modelos rodar, separados por vírgula: skin, hair_color, hair_type (qualquer combinação, sem repetição). Omitido = a análise completa, com os três. Valor desconhecido: 422 invalid_selection, nada cobrado. |
x-request-id | header | opcional | Seu identificador da requisição (até 80 caracteres). Gravado junto ao evento de uso para conciliação; não deduplica chamadas. |
x-end-user-id | header | opcional | Identificador da sua cliente final (até 160 caracteres, sem espaços), repassado ao modelo. Fora do formato, é ignorado. |
Modelos e atributos
Cada modelo devolve um ou dois atributos. O campo models aceita os ids da primeira coluna; a resposta traz, em result.attributes, exatamente os atributos dos modelos pedidos.
| Modelo | Descrição | Atributo |
|---|---|---|
skin | Pele — Tom de pele em nove níveis (very_light … deep) e subtom (cool, neutral, warm). | skin_tone, skin_undertone |
hair_color | Cor do cabelo — Nove categorias, de black a light_blonde, mais red, gray_white e other. | hair_color |
hair_type | Tipo de cabelo — Padrão do fio: straight, wavy, curly ou coily. | hair_pattern |
Resposta
200 OK, application/json. O envelope é fixo; result é o documento devolvido pelo modelo, repassado como está. Os mesmos números vêm nos headers X-Session-Id, X-Request-Id, X-Credits-Charged e X-Credits-Remaining.
| Campo | Tipo | Descrição |
|---|---|---|
session_id | string | Identificador do evento de uso (a sessão cobrada). Guarde para suporte e conciliação. |
request_id | string | Identificador da requisição no serviço MaIA. Cite os dois ids ao falar com o suporte. |
credits_charged | integer | Créditos efetivamente cobrados nesta chamada — os modelos que devolveram ao menos um atributo previsto. |
credits_remaining | integer | Saldo da conta após esta chamada. |
models | string[] | Modelos pedidos, na ordem canônica (skin, hair_color, hair_type). |
models_delivered | string[] | Modelos que devolveram ao menos um atributo com status predicted — os que foram cobrados. |
result.attributes.<atributo> | object | Por atributo pedido: status (predicted, abstained ou unsupported), value (o valor do vocabulário), score (softmax não calibrado — não é acurácia), model_version, photo_roles e requires_confirmation. |
result.quality / result.experimental / result.requires_confirmation | object · boolean | Diagnósticos de qualidade da foto por papel (front, side) e as flags do modelo. Os modelos são experimentais: peça confirmação à pessoa antes de usar um valor em uma decisão 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
}
}Status de cada atributo
Um 200 pode conter abstenções. Só o que foi previsto é cobrado:
| Status | Significado |
|---|---|
predicted | O modelo devolveu um valor do vocabulário (value) com o seu score. O modelo correspondente é cobrado. |
abstained | O modelo não teve confiança suficiente nesta foto (iluminação, enquadramento, resolução). Não cobrado. |
unsupported | O atributo não pode ser avaliado nesta foto (por exemplo, cabelo coberto). Não cobrado. |
Erros
| Status | Código | Significado | Crédito cobrado? |
|---|---|---|---|
400 | front_required | O campo front não foi enviado. | não |
400 | — | Campo de texto desconhecido (validação do corpo). | não |
401 | invalid_api_key | Chave ausente, inválida ou revogada. | não |
402 | insufficient_credits | Saldo menor que o necessário para os modelos pedidos; o corpo traz balance e required. | não |
413 | photo_too_large | Imagem acima de 6 MiB. Uploads muito acima do limite são cortados na recepção com um 413 genérico. | não |
415 | unsupported_media_type | Content-Type de um dos arquivos fora de image/jpeg e image/png. | não |
422 | unsupported_photo | Os bytes não são JPEG nem PNG (ou o arquivo está vazio). | não |
422 | invalid_selection | models contém um id desconhecido. | não |
422 | bad_photo | O modelo recusou a foto (rosto não detectado, foto muito pequena). Créditos devolvidos. | não |
422 | unusable_photo | Nenhum atributo pôde ser previsto (todos abstained ou unsupported). Tudo devolvido; o corpo traz session_id e request_id. | não |
429 | rate_limited | Mais de 20 requisições por minuto com a mesma chave (ou o serviço está no limite). Header Retry-After em segundos. | não |
503 | upstream_unavailable | O modelo não respondeu (falha ou 180 s de espera). Créditos devolvidos; o corpo traz session_id. | não |
503 | upstream_not_configured | O serviço de análise não está conectado neste ambiente. Nada é cobrado. | não |
Limites
- Até 6 MiB por arquivo, no máximo 2 arquivos (front + side), JPEG ou PNG estáticos.
- Chamada síncrona; o gateway aguarda o modelo por até 180 s. Configure o seu cliente HTTP com pelo menos 200 s.
- 20 requisições por minuto por chave de API e 120 por minuto por IP de origem.
Consentimento obrigatório: obtenha a autorização explícita da pessoa antes de enviar a foto (LGPD). A MaIA Scan não faz reconhecimento facial nem identificação; devolve análise cosmética, experimental, para personalização — não é diagnóstico. Campos com requires_confirmation devem ser confirmados com a pessoa.
Exemplos
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
Envia uma foto frontal com o produto a aplicar e recebe a mesma foto em PNG. Batom (category=lipstick, padrão): um tom de demonstração (shade) ou qualquer cor da sua marca (color, #RRGGBB), com acabamento e intensidade. Base (category=foundation): uma cor #RRGGBB com intensidade. Só a área da maquiagem muda. Síncrono.
Requisição
Corpo multipart/form-data com os campos abaixo (campos de texto desconhecidos são recusados com 400). Headers: Authorization (obrigatório), x-request-id e x-end-user-id (opcionais).
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
photo | arquivo | sim | Foto frontal, JPEG ou PNG (verificamos os bytes, não só o Content-Type). Até 6 MiB; lado menor de pelo menos 320 px; boca visível para batom. |
category | texto | opcional | lipstick (padrão) ou foundation. |
shade | texto | opcional | Batom: um dos tons de demonstração — rose, red, berry, coral, plum ou nude (ver GET /api/v1/try-on/shades). Exatamente um entre shade e color. |
color | texto | opcional | Qualquer cor em #RRGGBB (maiúsculas ou minúsculas). Batom: alternativa ao shade, para a paleta da sua marca. Base: obrigatório. |
finish | texto | opcional | Batom: matte (padrão), satin ou gloss. Não se aplica à base. |
intensity | texto | opcional | Inteiro de 0 a 100. Padrão 100 para batom e 70 para base. |
x-request-id | header | opcional | Seu identificador da requisição (até 80 caracteres), gravado no evento de uso. |
Cor da sua marca
Em vez de um tom de demonstração, envie color=#RRGGBB com o hex do seu produto — o modelo aplica exatamente essa cor, no acabamento e na intensidade pedidos. É o caminho para provar a sua própria paleta sem projeto de calibração.
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 maquiagem)
category=foundation aplica uma base na cor informada em color, com intensity (padrão 70). Não há shade nem finish para base. Mesma chave, mesmo endpoint, mesmo recibo nos 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: foundationResposta
200 OK, image/png — o corpo é a imagem renderizada. O recibo vem nos headers:
| Header | Descrição |
|---|---|
X-Session-Id | Identificador do evento de uso (a sessão cobrada). |
X-Request-Id | Identificador da requisição no serviço MaIA. |
X-Credits-Charged | Créditos cobrados por esta imagem. |
X-Credits-Remaining | Saldo da conta após esta chamada. |
X-TryOn-Category | a categoria renderizada: lipstick, foundation, blush, … ou full_look. |
X-TryOn-Color | A cor aplicada, em #RRGGBB maiúsculo — o hex do tom de demonstração ou a sua cor normalizada. |
X-TryOn-Finish | O acabamento aplicado (só batom). Não há fallback: o que você pediu é o que foi aplicado. |
X-Model-Version | Versão do modelo de render, quando informada. |
Cache-Control | no-store. A imagem não fica em nenhum cache do nosso 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>Erros
| Status | Código | Significado | Crédito cobrado? |
|---|---|---|---|
400 | photo_required | O campo photo não foi enviado. | não |
400 | — | Campo de texto desconhecido ou fora do formato (validação do corpo). | não |
401 | invalid_api_key | Chave ausente, inválida ou revogada. | não |
402 | insufficient_credits | Saldo insuficiente; o corpo traz balance e required. | não |
413 | photo_too_large | Foto acima de 6 MiB. Uploads muito acima do limite são cortados na recepção com um 413 genérico. | não |
422 | invalid_selection | category, shade, color, finish ou intensity fora do contrato (por exemplo shade e color juntos, cor sem #RRGGBB, base sem color). O corpo diz qual. | não |
422 | unsupported_photo | Os bytes não são JPEG nem PNG (ou o arquivo está vazio). | não |
422 | bad_photo | O modelo recusou a foto (rosto não frontal, boca não visível, lado menor abaixo de 320 px). Crédito devolvido. | não |
429 | rate_limited | Mais de 20 requisições por minuto com a mesma chave (ou o serviço está no limite). Header Retry-After em segundos. | não |
503 | upstream_unavailable | O serviço de render falhou ou não respondeu em 180 s. Crédito devolvido; tente de novo em instantes. | não |
503 | upstream_not_configured | O serviço de render não está conectado neste ambiente. Nada é cobrado. | não |
Limites
- JPEG ou PNG, até 6 MiB, lado menor ≥ 320 px.
- Chamada síncrona; o gateway aguarda o modelo por até 180 s. Configure o seu cliente HTTP com pelo menos 200 s.
- 20 requisições por minuto por chave de API e 120 por minuto por IP de origem.
- Cor simulada pode diferir do produto real: o render é experimental e trabalha em sRGB a partir do hex informado. Paleta calibrada com validação humana e outras categorias de maquiagem: sob projeto.
Exemplos — batom com tom de demonstração
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 o que POST /api/v1/try-on aceita: os tons de demonstração com o hex de referência, os acabamentos, o formato de cor personalizada, as faixas de intensidade, as categorias e o limite de upload. Não consome crédito.
Resposta
200 OK, application/json, Cache-Control: private, max-age=3600. Exige a mesma chave (401 sem ela).
| Campo | Tipo | Descrição |
|---|---|---|
shades[].id | string | Valor aceito no campo shade do try-on. |
shades[].hex | string | Cor de referência do tom (#RRGGBB) para exibir na sua interface. |
finishes | string[] | Valores aceitos no campo finish (batom). |
custom_color | boolean | true: o campo color aceita qualquer cor da sua marca. |
color_format | string | Formato aceito em color: #RRGGBB. |
intensity | object | Faixa e padrão da intensidade do batom: { min, max, default }. |
foundation_intensity | object | Faixa e padrão da intensidade da base: { min, max, default }. |
categories | string[] | Valores aceitos em category: lipstick, foundation. |
max_upload_bytes | integer | Limite de upload da foto em 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
}Exemplos
curl https://maiascan.ai/api/v1/try-on/shades \
-H "Authorization: Bearer msk_live_…"SDK no navegador (acesso antecipado)
Além da API por foto, o MaIA Try-On existe como um SDK para o navegador: treze simuladores (batom, base, blush, pó, corretivo, sombra, máscara, sobrancelhas, delineador, bronzer, contorno, iluminador e lápis de boca) e o Full Look, ao vivo pela câmera ou em foto, renderizados localmente no aparelho da cliente. Nenhuma imagem é enviada; a sua marca hospeda o pacote imutável na própria origem.
O SDK nunca chama esta API por conta própria. Batom e base podem receber um render final no servidor — pelo endpoint acima, com a chave da conta do lado do servidor — cobrado em créditos, como qualquer chamada; os demais produtos e o Full Look são prévias locais. O guia de integração (JavaScript, React, Angular, CSP, privacidade, versões) fica na área logada, e o acesso é liberado conta a conta.
Como obter o SDK hoje
- Crie uma conta em maiascan.ai (e-mail ou Google) e entre em Minha conta → SDK.
- Clique em "Pedir acesso": o SDK está em acesso antecipado e a equipe B4A libera conta a conta.
- Com o acesso liberado, a mesma página mostra a versão atual, o SHA-256 e o botão "Baixar pacote" (package.tgz). Hospede o conteúdo de package/ na sua origem em /vendor/maia-try-on/<versão>/ — o SDK exige mesma origem para workers, WASM e modelos.
- npm: com o acesso liberado, npm i @maiascan/try-on funciona pelo nosso registro privado (maiascan.ai/api/npm), autenticado com a chave de API da conta — as duas linhas do .npmrc estão na área logada. Nenhuma conta no npmjs.com é necessária.
Referência: vocabulários dos atributos
Os valores possíveis de value em result.attributes, por atributo. Os vocabulários são fixos por versão da API (api_version no envelope do modelo); valores novos chegam como mudança compatível.
| Atributo | Valores possíveis | Descrição |
|---|---|---|
skin_tone | very_light, light, light_medium, medium, medium_tan, medium_dark, dark, very_dark, deep | Nove níveis de tom de pele, do mais claro ao mais profundo. |
skin_undertone | cool, neutral, warm | Subtom da pele. |
hair_color | black, dark_brown, medium_brown, light_brown, dark_blonde, light_blonde, red, gray_white, other | Cor predominante do cabelo. |
hair_pattern | straight, wavy, curly, coily | Padrão do fio. |
Cada atributo vem com status predicted, abstained ou unsupported; score é um softmax não calibrado — trate como ordem de preferência, não como probabilidade nem acurácia.
Erros e códigos de status
Todo erro é JSON com um campo error estável (para o seu código) e message legível (para o log). Compare error, não message. Nenhum erro consome crédito: quando a falha acontece depois da reserva (422 bad_photo ou unusable_photo, 429, 503), a devolução é gravada na mesma transação e o corpo traz session_id.
| Status | Significado |
|---|---|
400 | Requisição malformada: campo obrigatório ausente ou campo de texto desconhecido. |
401 | invalid_api_key — chave ausente, inválida ou revogada. |
402 | insufficient_credits — saldo menor que o necessário; o corpo traz balance e required. |
413 | photo_too_large — imagem acima de 6 MiB. |
415 | unsupported_media_type — Content-Type fora de image/jpeg e image/png (scan). |
422 | Entrada válida em forma, inválida em conteúdo: invalid_selection, unsupported_photo, bad_photo, unusable_photo (scan). |
429 | rate_limited — limite por chave ou do serviço; aguarde Retry-After segundos e repita com backoff. |
503 | upstream_unavailable (crédito devolvido) ou 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
}Limites, idempotência e x-request-id
- Rate limit: 20 requisições por minuto por chave de API em todas as rotas /api/v1 (429 rate_limited com Retry-After), além de 120 por minuto por IP de origem. Para volumes maiores, fale com a gente.
- Idempotência: as chamadas não são idempotentes — cada 200 consome créditos. Não repita automaticamente uma chamada que devolveu 200; repita apenas erros 429 e 503 (que não cobram), respeitando Retry-After e com backoff exponencial.
- x-request-id: envie o seu identificador (até 80 caracteres). Ele é gravado no evento de uso e aparece na conciliação; use-o com session_id / X-Session-Id e request_id / X-Request-Id ao falar com o suporte.
- Timeouts: o gateway aguarda o modelo por até 180 s. Configure o seu cliente HTTP com pelo menos 200 s para não abandonar uma chamada que ainda será cobrada e respondida.
Tratamento de dados e consentimento
- Consentimento: você é responsável por obter a autorização explícita da pessoa antes de enviar qualquer foto, nos termos da LGPD. Na nossa própria demo o texto usado é: "Autorizo o processamento desta foto apenas para gerar a simulação; ela não é armazenada."
- Fotos no gateway: ficam em memória apenas durante a requisição e são encaminhadas uma vez ao modelo. O gateway não grava fotos em disco, banco ou logs — os logs registram tamanho, operação, latência, status e identificadores de requisição.
- No serviço MaIA: nada é retido nem usado para treino (retained: false, used_for_training: false no envelope). Só o resultado — JSON ou PNG — volta para você, com Cache-Control: no-store.
- O que não fazemos: reconhecimento facial, identificação de pessoas, inferência de traços protegidos ou diagnóstico médico. A análise é cosmética e experimental; campos com requires_confirmation devem ser confirmados com a pessoa.
- Registro de uso: por requisição guardamos conta, chave, endpoint, status, créditos, latência, x-request-id e o request_id do modelo — é o que aparece na sua página de uso.
Base URL, versão e contato
https://maiascan.ai/api- Base URL: https://maiascan.ai/api — sempre HTTPS. As rotas públicas ficam sob /v1.
- Versionamento: a versão vai no caminho (v1). Mudanças compatíveis (campos novos no JSON, headers novos, tons novos, valores novos nos vocabulários) chegam sem troca de versão; qualquer mudança incompatível nasce como /v2, com /v1 mantida em paralelo por um período anunciado.
- Status do gateway: GET https://maiascan.ai/api/health devolve { "status": "ok", "commit": "…" } — sem autenticação.
- Suporte técnico e comercial: comercial@b4a.ai.
Precisa de mais volume, limites maiores por chave, paleta calibrada com validação humana, outras categorias de maquiagem, MaIA Beauty Advisor ou um contrato enterprise? Fale com a gente — a B4A entrega projetos completos em cima da mesma API.