API grátis de centralização de cartas: PSA e fotos
O Centering Lab é uma API REST gratuita de centralização de cartas, sem chave API. Em https://centeringlab.com/api/v1, retorna medições de fotos, proporções e limites PSA, BGS, CGC ou SGC baseados apenas na centralização. Não prevê a nota final nem autentica cartas. Chame pelo seu servidor. OpenAPI.
Início rápido
Execute curl no terminal. Os dois eixos da frente foram informados, mas falta o verso: incomplete é true. PSA 10 é um limite de centralização, não previsão de nota final.
POST /api/v1/grade
Requisição
curl --fail-with-body 'https://centeringlab.com/api/v1/grade' \
-H 'Content-Type: application/json' \
--data '{"front_lr":0.55,"front_tb":"50/50","house":"PSA"}'Resposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"front": {
"ratios": {
"lr": 55,
"tb": 50
}
},
"combined": {
"PSA": {
"maximum_grade": 10,
"source_status": "official"
}
},
"normalizations": [
{
"field": "front_lr",
"input": 0.55,
"ratio": "55/45",
"note": "0.55 read as 55/45"
}
],
"incomplete": true,
"missing_faces": [
"back"
],
"disclaimer": "This is a ceiling from centering alone, not a prediction of the final grade."
}Endpoints e campos
Proporções conhecidas
POST /grade exige pelo menos um de front_lr, front_tb, back_lr, back_tb. Normaliza para o lado maior. Aceita percentual (55), fração (0.55) e pares que somam 100 (55/45) ou 1 (0.55/0.45). Separadores: /, -, –, —, :, x e espaços; % opcional. O escalar 1 é ambíguo e recusado. L/R ou left/right só em *_lr; T/B ou top/bottom só em *_tb.
house filtra PSA, BGS, CGC ou SGC. normalizations declara conversões de frações. missing_axes, missing_faces e incomplete indicam dados ausentes que podem baixar o limite. combined combina faces; limiting_face e limiting_axis identificam a restrição. Cada limite inclui fontes e status.
Campos do contrato (nomes JSON exatos)
input: front_lr, front_tb, back_lr, back_tb, house
output: front, front.ratios, front.ratios.lr, front.ratios.tb, front.missing_axes, front.ceilings, front.ceilings.PSA, front.ceilings.PSA.maximum_grade, front.ceilings.PSA.label, front.ceilings.PSA.rank, front.ceilings.PSA.limiting_face, front.ceilings.PSA.limiting_axis, front.ceilings.PSA.distance_to_next, front.ceilings.PSA.next_grade, front.ceilings.PSA.next_label, front.ceilings.PSA.borderline, front.ceilings.PSA.unconstrained, front.ceilings.PSA.source_status, front.ceilings.PSA.standard_status, front.ceilings.PSA.source, front.ceilings.PSA.sources, front.ceilings.PSA.verified, front.ceilings.PSA.verification, front.ceilings.BGS, front.ceilings.BGS.maximum_grade, front.ceilings.BGS.label, front.ceilings.BGS.rank, front.ceilings.BGS.limiting_face, front.ceilings.BGS.limiting_axis, front.ceilings.BGS.distance_to_next, front.ceilings.BGS.next_grade, front.ceilings.BGS.next_label, front.ceilings.BGS.borderline, front.ceilings.BGS.unconstrained, front.ceilings.BGS.source_status, front.ceilings.BGS.standard_status, front.ceilings.BGS.source, front.ceilings.BGS.sources, front.ceilings.BGS.verified, front.ceilings.BGS.verification, front.ceilings.CGC, front.ceilings.CGC.maximum_grade, front.ceilings.CGC.label, front.ceilings.CGC.rank, front.ceilings.CGC.limiting_face, front.ceilings.CGC.limiting_axis, front.ceilings.CGC.distance_to_next, front.ceilings.CGC.next_grade, front.ceilings.CGC.next_label, front.ceilings.CGC.borderline, front.ceilings.CGC.unconstrained, front.ceilings.CGC.source_status, front.ceilings.CGC.standard_status, front.ceilings.CGC.source, front.ceilings.CGC.sources, front.ceilings.CGC.verified, front.ceilings.CGC.verification, front.ceilings.SGC, front.ceilings.SGC.maximum_grade, front.ceilings.SGC.label, front.ceilings.SGC.rank, front.ceilings.SGC.limiting_face, front.ceilings.SGC.limiting_axis, front.ceilings.SGC.distance_to_next, front.ceilings.SGC.next_grade, front.ceilings.SGC.next_label, front.ceilings.SGC.borderline, front.ceilings.SGC.unconstrained, front.ceilings.SGC.source_status, front.ceilings.SGC.standard_status, front.ceilings.SGC.source, front.ceilings.SGC.sources, front.ceilings.SGC.verified, front.ceilings.SGC.verification, back, back.ratios, back.ratios.lr, back.ratios.tb, back.missing_axes, back.ceilings, back.ceilings.PSA, back.ceilings.PSA.maximum_grade, back.ceilings.PSA.label, back.ceilings.PSA.rank, back.ceilings.PSA.limiting_face, back.ceilings.PSA.limiting_axis, back.ceilings.PSA.distance_to_next, back.ceilings.PSA.next_grade, back.ceilings.PSA.next_label, back.ceilings.PSA.borderline, back.ceilings.PSA.unconstrained, back.ceilings.PSA.source_status, back.ceilings.PSA.standard_status, back.ceilings.PSA.source, back.ceilings.PSA.sources, back.ceilings.PSA.verified, back.ceilings.PSA.verification, back.ceilings.BGS, back.ceilings.BGS.maximum_grade, back.ceilings.BGS.label, back.ceilings.BGS.rank, back.ceilings.BGS.limiting_face, back.ceilings.BGS.limiting_axis, back.ceilings.BGS.distance_to_next, back.ceilings.BGS.next_grade, back.ceilings.BGS.next_label, back.ceilings.BGS.borderline, back.ceilings.BGS.unconstrained, back.ceilings.BGS.source_status, back.ceilings.BGS.standard_status, back.ceilings.BGS.source, back.ceilings.BGS.sources, back.ceilings.BGS.verified, back.ceilings.BGS.verification, back.ceilings.CGC, back.ceilings.CGC.maximum_grade, back.ceilings.CGC.label, back.ceilings.CGC.rank, back.ceilings.CGC.limiting_face, back.ceilings.CGC.limiting_axis, back.ceilings.CGC.distance_to_next, back.ceilings.CGC.next_grade, back.ceilings.CGC.next_label, back.ceilings.CGC.borderline, back.ceilings.CGC.unconstrained, back.ceilings.CGC.source_status, back.ceilings.CGC.standard_status, back.ceilings.CGC.source, back.ceilings.CGC.sources, back.ceilings.CGC.verified, back.ceilings.CGC.verification, back.ceilings.SGC, back.ceilings.SGC.maximum_grade, back.ceilings.SGC.label, back.ceilings.SGC.rank, back.ceilings.SGC.limiting_face, back.ceilings.SGC.limiting_axis, back.ceilings.SGC.distance_to_next, back.ceilings.SGC.next_grade, back.ceilings.SGC.next_label, back.ceilings.SGC.borderline, back.ceilings.SGC.unconstrained, back.ceilings.SGC.source_status, back.ceilings.SGC.standard_status, back.ceilings.SGC.source, back.ceilings.SGC.sources, back.ceilings.SGC.verified, back.ceilings.SGC.verification, combined, combined.PSA, combined.PSA.maximum_grade, combined.PSA.label, combined.PSA.rank, combined.PSA.limiting_face, combined.PSA.limiting_axis, combined.PSA.distance_to_next, combined.PSA.next_grade, combined.PSA.next_label, combined.PSA.borderline, combined.PSA.unconstrained, combined.PSA.source_status, combined.PSA.standard_status, combined.PSA.source, combined.PSA.sources, combined.PSA.verified, combined.PSA.verification, combined.BGS, combined.BGS.maximum_grade, combined.BGS.label, combined.BGS.rank, combined.BGS.limiting_face, combined.BGS.limiting_axis, combined.BGS.distance_to_next, combined.BGS.next_grade, combined.BGS.next_label, combined.BGS.borderline, combined.BGS.unconstrained, combined.BGS.source_status, combined.BGS.standard_status, combined.BGS.source, combined.BGS.sources, combined.BGS.verified, combined.BGS.verification, combined.CGC, combined.CGC.maximum_grade, combined.CGC.label, combined.CGC.rank, combined.CGC.limiting_face, combined.CGC.limiting_axis, combined.CGC.distance_to_next, combined.CGC.next_grade, combined.CGC.next_label, combined.CGC.borderline, combined.CGC.unconstrained, combined.CGC.source_status, combined.CGC.standard_status, combined.CGC.source, combined.CGC.sources, combined.CGC.verified, combined.CGC.verification, combined.SGC, combined.SGC.maximum_grade, combined.SGC.label, combined.SGC.rank, combined.SGC.limiting_face, combined.SGC.limiting_axis, combined.SGC.distance_to_next, combined.SGC.next_grade, combined.SGC.next_label, combined.SGC.borderline, combined.SGC.unconstrained, combined.SGC.source_status, combined.SGC.standard_status, combined.SGC.source, combined.SGC.sources, combined.SGC.verified, combined.SGC.verification, normalizations, normalizations[].field, normalizations[].input, normalizations[].ratio, normalizations[].note, incomplete, missing_faces, summary, disclaimerCampos do contrato (nomes JSON exatos)
input: maximum_grade, label, rank, limiting_face, limiting_axis, distance_to_next, next_grade, next_label, borderline, unconstrained, source_status, standard_status, source, sources, verified, verification
output: maximum_grade, label, rank, limiting_face, limiting_axis, distance_to_next, next_grade, next_label, borderline, unconstrained, source_status, standard_status, source, sources, verified, verificationMedição de fotografia
POST /measure exige face: front ou back. card_size padrão é standard (63×88 mm); small é 59×86 mm. Uma única fonte: image_url HTTPS pública na porta 443 ou image_base64 puro sem prefixo data-URL. Endereços privados, credenciais e respostas não imagem são recusados, inclusive em redirecionamentos. REST também aceita um openaiFileIdRefs do runtime GPT Actions; em integrações comuns use URL ou base64. Envie raster de um quadro, preferivelmente JPG, PNG ou WebP.
HTTP 200 pode trazer status ok, needs-review ou failed; apenas ok expõe ceilings. Confira code, confidence, warnings, lr e tb. uncertainty_pp e sigma_pp usam pontos percentuais; stations_major_percent contém amostras. Resultados incertos exigem nova foto ou revisão em adjust_url. O exemplo envia uma imagem pequena uniforme de propósito: NO_CARD é uma falha real, não medição bem-sucedida.
Campos do contrato (nomes JSON exatos)
input: face, card_size, image_url, image_base64, openaiFileIdRefs, openaiFileIdRefs[].name, openaiFileIdRefs[].id, openaiFileIdRefs[].mime_type, openaiFileIdRefs[].download_link
output: status, code, face, card_size, lr, lr.ratio, lr.major_percent, lr.minor_percent, lr.uncertainty_pp, lr.sigma_pp, lr.worst_station_px, lr.stations_major_percent, tb, tb.ratio, tb.major_percent, tb.minor_percent, tb.uncertainty_pp, tb.sigma_pp, tb.worst_station_px, tb.stations_major_percent, confidence, warnings, ceilings, ceilings.PSA, ceilings.PSA.maximum_grade, ceilings.PSA.label, ceilings.PSA.rank, ceilings.PSA.limiting_face, ceilings.PSA.limiting_axis, ceilings.PSA.distance_to_next, ceilings.PSA.next_grade, ceilings.PSA.next_label, ceilings.PSA.borderline, ceilings.PSA.unconstrained, ceilings.PSA.source_status, ceilings.PSA.standard_status, ceilings.PSA.source, ceilings.PSA.sources, ceilings.PSA.verified, ceilings.PSA.verification, ceilings.BGS, ceilings.BGS.maximum_grade, ceilings.BGS.label, ceilings.BGS.rank, ceilings.BGS.limiting_face, ceilings.BGS.limiting_axis, ceilings.BGS.distance_to_next, ceilings.BGS.next_grade, ceilings.BGS.next_label, ceilings.BGS.borderline, ceilings.BGS.unconstrained, ceilings.BGS.source_status, ceilings.BGS.standard_status, ceilings.BGS.source, ceilings.BGS.sources, ceilings.BGS.verified, ceilings.BGS.verification, ceilings.CGC, ceilings.CGC.maximum_grade, ceilings.CGC.label, ceilings.CGC.rank, ceilings.CGC.limiting_face, ceilings.CGC.limiting_axis, ceilings.CGC.distance_to_next, ceilings.CGC.next_grade, ceilings.CGC.next_label, ceilings.CGC.borderline, ceilings.CGC.unconstrained, ceilings.CGC.source_status, ceilings.CGC.standard_status, ceilings.CGC.source, ceilings.CGC.sources, ceilings.CGC.verified, ceilings.CGC.verification, ceilings.SGC, ceilings.SGC.maximum_grade, ceilings.SGC.label, ceilings.SGC.rank, ceilings.SGC.limiting_face, ceilings.SGC.limiting_axis, ceilings.SGC.distance_to_next, ceilings.SGC.next_grade, ceilings.SGC.next_label, ceilings.SGC.borderline, ceilings.SGC.unconstrained, ceilings.SGC.source_status, ceilings.SGC.standard_status, ceilings.SGC.source, ceilings.SGC.sources, ceilings.SGC.verified, ceilings.SGC.verification, adjust_url, advice, elapsed_ms, image_bytes, summary, disclaimerPOST /api/v1/measure
Requisição
curl --fail-with-body 'https://centeringlab.com/api/v1/measure' \
-H 'Content-Type: application/json' \
--data '{"face":"front","card_size":"standard","image_base64":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAD0lEQVQImWNQwAEYhpYEAGFPGAHjXOFDAAAAAElFTkSuQmCC"}'Resposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"status": "failed",
"code": "NO_CARD",
"face": "front",
"card_size": "standard",
"lr": null,
"tb": null,
"confidence": null,
"warnings": [],
"ceilings": null,
"adjust_url": "https://centeringlab.com/"
}Salve sua foto como card.jpg. Esta resposta usa a foto de demonstração do site: a incerteza gera needs-review e ceilings é null. Sua foto terá suas próprias medidas.
POST /api/v1/measure
Requisição
python3 - <<'PY' > measure.json
import base64, json
from pathlib import Path
print(json.dumps({
'face': 'front', 'card_size': 'standard',
'image_base64': base64.b64encode(Path('card.jpg').read_bytes()).decode('ascii'),
}))
PY
curl --fail-with-body 'https://centeringlab.com/api/v1/measure' \
-H 'Content-Type: application/json' \
--data-binary @measure.jsonResposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"status": "needs-review",
"code": "HIGH_UNCERTAINTY",
"face": "front",
"card_size": "standard",
"lr": {
"ratio": "56/44",
"major_percent": 55.54242922739353,
"minor_percent": 44.45757077260647,
"uncertainty_pp": 5.1,
"sigma_pp": 2.3393336872317274,
"worst_station_px": 350.163778228702,
"stations_major_percent": [
55.54242922739353,
54.38358480163707,
53.25627521942576
]
},
"tb": {
"ratio": "52/48",
"major_percent": 52.059885599520676,
"minor_percent": 47.940114400479324,
"uncertainty_pp": 6.4,
"sigma_pp": 2.9286347555409855,
"worst_station_px": 250.03684789689908,
"stations_major_percent": [
52.059885599520676,
51.766308753028554,
51.468031630625774
]
},
"confidence": 0.8603421926529179,
"warnings": [
"GET_CLOSER"
],
"ceilings": null,
"adjust_url": "https://centeringlab.com/"
}Padrões e fontes
GET /standards aceita house e face opcionais. official, interpreted e approximate descrevem evidência, não garantias de precisão. bands[].status vale para cada faixa; source, sources, verified e verification informam a origem. TAG está excluído. SGC não publica tabela de centralização do verso: as faixas estão vazias e o verso sozinho não estabelece limite SGC.
Campos do contrato (nomes JSON exatos)
input: house, face
output: standards, standards[].house, standards[].face, standards[].bands, standards[].bands[].value, standards[].bands[].label, standards[].bands[].rank, standards[].bands[].loose, standards[].bands[].tight, standards[].bands[].status, standards[].source, standards[].sources, standards[].status, standards[].verified, standards[].verification, standards[].note, rounding_rule, tag_note, summary, disclaimerGET /api/v1/standards?house=PSA&face=front
Requisição
curl --fail-with-body 'https://centeringlab.com/api/v1/standards?house=PSA&face=front'Resposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"standards": [
{
"house": "PSA",
"face": "front",
"bands": [
{
"value": 10,
"label": "GEM MT",
"rank": 100,
"loose": 55,
"status": "official"
}
],
"status": "official",
"source": "https://www.psacard.com/gradingstandards",
"note": "Published percentage thresholds. Only the listed centering bands are used; no missing grades are invented."
}
],
"tag_note": "TAG is excluded because its centering assessment is proprietary and is not represented by these public percentage bands."
}Status e esquema
GET /health retorna status, nome, versão e disclaimer. GET /openapi.json retorna OpenAPI 3.1.0. O esquema de medição é voltado ao GPT Actions (URL ou referência de arquivo runtime); REST também aceita base64 conforme os campos acima.
GET /api/v1/health
Requisição
curl --fail-with-body 'https://centeringlab.com/api/v1/health'Resposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"status": "ok",
"name": "centering-lab",
"version": "1.1.2",
"disclaimer": "This is a ceiling from centering alone, not a prediction of the final grade."
}GET /api/v1/openapi.json
Requisição
curl --fail-with-body 'https://centeringlab.com/api/v1/openapi.json'Resposta HTTP 200
Trecho de uma resposta HTTP real local; campos e faixas adicionais foram omitidos. Chaves JSON e mensagens do servidor permanecem em inglês.
{
"openapi": "3.1.0",
"info": {
"title": "Centering Lab API",
"version": "1.1.2"
},
"servers": [
{
"url": "https://centeringlab.com"
}
]
}JavaScript e Python
Use fetch de Node no servidor. Os exemplos enviam a requisição inicial. Python usa a biblioteca padrão. Confira erros HTTP e, para medir, também status mesmo com HTTP 200.
JavaScript · Node
const response = await fetch('https://centeringlab.com/api/v1/grade', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({"front_lr":0.55,"front_tb":"50/50","house":"PSA"}),
});
const result = await response.json();
if (!response.ok) throw new Error(result.code + ': ' + result.message);
console.log(result);Python · urllib
import json
from urllib.request import Request, urlopen
from urllib.error import HTTPError
request = Request(
'https://centeringlab.com/api/v1/grade',
data=json.dumps({"front_lr":0.55,"front_tb":"50/50","house":"PSA"}).encode('utf-8'),
headers={'Content-Type': 'application/json'},
method='POST',
)
try:
with urlopen(request, timeout=20) as response:
print(json.load(response))
except HTTPError as error:
print(error.code, json.load(error))
raiseErros e novas tentativas
Erros HTTP têm status, code, message e disclaimer. A tabela cobre REST, sem erros de protocolo MCP nem estatísticas privadas. UNSUPPORTED_ENCODING é 415 para JSON comprimido e 400 para resposta de imagem comprimida. Códigos do detector chegam com HTTP 200.
| Código | HTTP | Significado | O que fazer |
|---|---|---|---|
BODY_TOO_LARGE | 413 | Tamanho excedido | Reduza bytes ou pixels; base64 também conta no corpo JSON. |
EMPTY_IMAGE | 400 | Imagem não decodificável | Envie um raster compatível, de preferência JPG, PNG ou WebP; remova o prefixo data-URL do base64. |
IMAGE_DNS_FAILED | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
IMAGE_DOWNLOAD_FAILED | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
IMAGE_DOWNLOAD_TIMEOUT | 504 | Tempo excedido | Use imagem menor ou host mais rápido; se necessário, use o site. |
IMAGE_REDIRECT_LIMIT | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
IMAGE_TOO_LARGE | 413 | Tamanho excedido | Reduza bytes ou pixels; base64 também conta no corpo JSON. |
IMAGE_TOO_MANY_PIXELS | 413 | Tamanho excedido | Reduza bytes ou pixels; base64 também conta no corpo JSON. |
INTERNAL_ERROR | 500 | Falha do servidor ou worker | Aguarde, reduza a foto ou use o site. |
INVALID_ARGUMENTS | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
INVALID_BASE64 | 400 | Imagem não decodificável | Envie um raster compatível, de preferência JPG, PNG ou WebP; remova o prefixo data-URL do base64. |
INVALID_BODY | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
INVALID_HOST | 403 | Host ou origem recusados | Chame centeringlab.com do seu servidor, não do navegador de outro site. |
INVALID_HTTP | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
INVALID_IMAGE | 400 | Imagem não decodificável | Envie um raster compatível, de preferência JPG, PNG ou WebP; remova o prefixo data-URL do base64. |
INVALID_IMAGE_URL | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
INVALID_INPUT | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
INVALID_JSON | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
INVALID_ORIGIN | 403 | Host ou origem recusados | Chame centeringlab.com do seu servidor, não do navegador de outro site. |
INVALID_RATIO | 400 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
JSON_REQUIRED | 415 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
MEASURE_QUEUE_FULL | 503 | Serviço lotado | Respeite Retry-After e aumente o intervalo entre tentativas. |
MEASURE_TIMEOUT | 504 | Tempo excedido | Use imagem menor ou host mais rápido; se necessário, use o site. |
MEASURE_WORKER_FAILED | 500 | Falha do servidor ou worker | Aguarde, reduza a foto ou use o site. |
METHOD_NOT_ALLOWED | 405 | Rota ou método indisponível | Use os endpoints e métodos documentados. |
NOT_AN_IMAGE | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
NOT_FOUND | 404 | Rota ou método indisponível | Use os endpoints e métodos documentados. |
RATE_LIMIT_CAPACITY | 503 | Serviço lotado | Respeite Retry-After e aumente o intervalo entre tentativas. |
RATE_LIMIT_DAY | 429 | Cota atingida | Respeite Retry-After em segundos; a cota diária reinicia à meia-noite UTC. |
RATE_LIMIT_MINUTE | 429 | Cota atingida | Respeite Retry-After em segundos; a cota diária reinicia à meia-noite UTC. |
REQUEST_CANCELLED | 499 | Requisição cancelada | Tente de novo apenas se ainda precisar do resultado. |
REQUEST_CAPACITY | 503 | Serviço lotado | Respeite Retry-After e aumente o intervalo entre tentativas. |
UNSAFE_IMAGE_URL | 400 | URL recusada ou inacessível | Use imagem HTTPS pública na porta 443 sem credenciais; confira DNS, redirecionamentos e resposta. |
UNSUPPORTED_ENCODING | 400 / 415 | Requisição ou proporção inválida | Corrija os campos; envie JSON válido sem compressão. |
UNSUPPORTED_IMAGE | 400 | Imagem não decodificável | Envie um raster compatível, de preferência JPG, PNG ou WebP; remova o prefixo data-URL do base64. |
Códigos do detector: HIGH_UNCERTAINTY, NEEDS_REVIEW, LOW_CONFIDENCE, NO_MEASUREMENT, NO_CARD, CARD_TOO_SMALL, CARD_CUT_OFF, NO_PRINTED_BORDER. failed e needs-review não têm limites de graduação. Fotografe a carta inteira de cima, sem sleeve, em fundo escuro plano, ou use o editor manual do site.
Limites de uso
Cotas por IP e compartilhadas com os grupos correspondentes. Grade e standards dividem um contador por minuto; health e OpenAPI outro. Janelas de minuto fixas e dias UTC; sem cota diária para chamadas simples/protocolo. Base64 expande os bytes e conta no corpo JSON: o limite completo da imagem pode não caber.
| Limite | Valor atual |
|---|---|
POST /measure · IP | 20 por minuto; 200 por dia UTC |
POST /grade + GET /standards · IP | 120 por minuto; Sem cota diária no limitador |
GET /health + GET /openapi.json · IP | 120 por minuto; Sem cota diária no limitador |
Corpo JSON | 12 MiB (12582912 bytes) |
Bytes da imagem decodificada | 15 MiB (15728640 bytes) |
Pixels decodificados (todos os quadros) | 40000000 |
Medição, incluindo fila | 15 s |
Download da imagem | 10 s |
Medições ativas | 2 |
Medições na fila | 8 |
Requisições HTTP em andamento | 16 |
429 e 503 de capacidade incluem Retry-After em segundos. Fila cheia e REQUEST_CAPACITY: 5 segundos; capacidade do limitador: 60. Respeite o cabeçalho com intervalos crescentes. Capacidade compartilhada, sem reserva por cliente e sem SLA de disponibilidade ou latência.
Navegador, CORS e privacidade
O navegador de outro site recebe 403 INVALID_ORIGIN: use seu backend. Não precisa de chave, e adicioná-la não abre CORS. Fotos API chegam ao servidor, são processadas apenas em memória e não são salvas em disco. O site processa no dispositivo. Sem logs por requisição: apenas contagens agregadas por endpoint/tool e código de resultado. Privacidade e termos.
MCP e outras informações
https://centeringlab.com/mcp oferece aos clientes AI as mesmas três ferramentas e motor. REST oferece chamadas HTTP diretas. Leia AI e MCP, como funciona e sobre o Centering Lab.
Perguntas sobre a API
A API de centralização de cartas é gratuita para desenvolvedores?
Sim. Todos os endpoints são gratuitos, sem conta nem plano pago. Limites se aplicam; não autentica cartas nem prevê a nota final.
Integrações REST precisam de chave API?
Não. Envie requisições válidas pelo seu servidor; a restrição de origem do navegador continua ativa.
Quais são as cotas desta API de centralização?
Medição: 20 por minuto e 200 por dia UTC por IP. Grade e standards dividem 120 por minuto por IP. Respeite Retry-After e limites de tamanho e capacidade.
A API REST salva fotografias enviadas?
Não. Chegam ao servidor, mas são processadas apenas em memória. Sem logs individuais; somente contagens agregadas e códigos. O site processa fotos no dispositivo.
Outro site pode chamar diretamente pelo navegador?
Não. Recebe 403 INVALID_ORIGIN. Chame pelo seu backend, sem chave API.
Qual a diferença entre esta API REST e MCP?
REST usa endpoints HTTP; MCP oferece três ferramentas aos clientes AI. Compartilham motor e padrões. API/MCP processam no servidor; o site processa localmente.
Centering Lab · Atualizado em