API gratis de centrado de cartas: PSA y fotos
Centering Lab es una API REST gratuita de centrado de cartas, sin clave API. En https://centeringlab.com/api/v1 devuelve mediciones de fotos, proporciones y límites PSA, BGS, CGC o SGC basados solo en el centrado. No predice la nota final ni autentica cartas. Llámala desde tu servidor. OpenAPI.
Inicio rápido
Ejecuta curl en el terminal. Ambos ejes del anverso están presentes, pero falta el reverso: incomplete es true. PSA 10 es un límite por centrado, no una predicción de nota final.
POST /api/v1/grade
Solicitud
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"}'Respuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en 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 y campos
Proporciones conocidas
POST /grade requiere al menos uno de front_lr, front_tb, back_lr, back_tb. Normaliza al lado mayor. Acepta porcentajes (55), fracciones (0.55) y pares que sumen 100 (55/45) o 1 (0.55/0.45). Separadores: /, -, –, —, :, x y espacios; % opcional. El escalar 1 es ambiguo y se rechaza. Sufijos L/R o left/right solo para *_lr; T/B o top/bottom para *_tb.
house filtra PSA, BGS, CGC o SGC. normalizations declara conversiones; missing_axes, missing_faces e incomplete indican datos ausentes que pueden reducir el límite. combined combina caras; limiting_face y limiting_axis señalan la restricción. Cada límite incluye estado y fuentes.
Campos del contrato (nombres JSON exactos)
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 del contrato (nombres JSON exactos)
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, verificationMedición de fotografías
POST /measure exige face: front o back. card_size predeterminado es standard (63×88 mm); small es 59×86 mm. Envía exactamente una fuente: image_url HTTPS pública en el puerto 443 o image_base64 sin prefijo data-URL. Se rechazan redes privadas, credenciales y respuestas no imagen, también en redirecciones. REST admite además un openaiFileIdRefs del runtime GPT Actions; para integraciones normales usa URL o base64. Utiliza un raster de un solo fotograma, preferiblemente JPG, PNG o WebP.
HTTP 200 puede contener status ok, needs-review o failed; solo ok tiene ceilings. Revisa code, confidence, warnings, lr y tb. uncertainty_pp y sigma_pp son puntos porcentuales; stations_major_percent contiene muestras. Si hay incertidumbre, repite la foto o revisa adjust_url. El ejemplo envía una imagen pequeña uniforme deliberadamente: NO_CARD es un fallo real, no una medición exitosa.
Campos del contrato (nombres JSON exactos)
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
Solicitud
curl --fail-with-body 'https://centeringlab.com/api/v1/measure' \
-H 'Content-Type: application/json' \
--data '{"face":"front","card_size":"standard","image_base64":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAD0lEQVQImWNQwAEYhpYEAGFPGAHjXOFDAAAAAElFTkSuQmCC"}'Respuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en 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/"
}Guarda tu fotografía como card.jpg. Esta respuesta usa la foto demo del sitio: la incertidumbre provoca needs-review y ceilings es null. Tu imagen tendrá sus propias medidas.
POST /api/v1/measure
Solicitud
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.jsonRespuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en 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/"
}Estándares y fuentes
GET /standards admite house y face opcionales. official, interpreted y approximate son estados de evidencia, no garantías de precisión. bands[].status corresponde a cada banda; source, sources, verified y verification explican la procedencia. TAG está excluido. SGC no publica tabla de centrado del reverso: sus bandas están vacías y el reverso solo no establece un límite SGC.
Campos del contrato (nombres JSON exactos)
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
Solicitud
curl --fail-with-body 'https://centeringlab.com/api/v1/standards?house=PSA&face=front'Respuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en 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."
}Estado y esquema
GET /health devuelve estado, nombre, versión y disclaimer. GET /openapi.json devuelve OpenAPI 3.1.0. Su esquema de medición está orientado a GPT Actions (URL o referencia runtime); REST también acepta base64 según los campos anteriores.
GET /api/v1/health
Solicitud
curl --fail-with-body 'https://centeringlab.com/api/v1/health'Respuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en 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
Solicitud
curl --fail-with-body 'https://centeringlab.com/api/v1/openapi.json'Respuesta HTTP 200
Extracto de una respuesta HTTP real local; se omiten campos y otras bandas. Las claves JSON y los mensajes del servidor siguen en inglés.
{
"openapi": "3.1.0",
"info": {
"title": "Centering Lab API",
"version": "1.1.2"
},
"servers": [
{
"url": "https://centeringlab.com"
}
]
}JavaScript y Python
Usa fetch de Node desde el servidor. Ambos ejemplos envían la solicitud inicial. Python utiliza la biblioteca estándar. Comprueba errores HTTP y, en mediciones, también status con 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))
raiseErrores y reintentos
Los errores HTTP contienen status, code, message y disclaimer. La tabla cubre REST, sin errores de protocolo MCP ni estadísticas privadas. UNSUPPORTED_ENCODING es 415 para JSON comprimido y 400 para imágenes comprimidas. Los códigos del detector llegan con HTTP 200.
| Código | HTTP | Significado | Qué hacer |
|---|---|---|---|
BODY_TOO_LARGE | 413 | Tamaño excesivo | Reduce bytes o píxeles; el base64 también cuenta en el cuerpo JSON. |
EMPTY_IMAGE | 400 | No se puede decodificar la imagen | Envía una imagen raster compatible, preferiblemente JPG, PNG o WebP; elimina el prefijo data-URL del base64. |
IMAGE_DNS_FAILED | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
IMAGE_DOWNLOAD_FAILED | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
IMAGE_DOWNLOAD_TIMEOUT | 504 | Tiempo agotado | Usa una imagen menor o un host más rápido; también puedes usar el sitio. |
IMAGE_REDIRECT_LIMIT | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
IMAGE_TOO_LARGE | 413 | Tamaño excesivo | Reduce bytes o píxeles; el base64 también cuenta en el cuerpo JSON. |
IMAGE_TOO_MANY_PIXELS | 413 | Tamaño excesivo | Reduce bytes o píxeles; el base64 también cuenta en el cuerpo JSON. |
INTERNAL_ERROR | 500 | Fallo de servidor o worker | Reintenta con espera, reduce la foto o usa el sitio. |
INVALID_ARGUMENTS | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
INVALID_BASE64 | 400 | No se puede decodificar la imagen | Envía una imagen raster compatible, preferiblemente JPG, PNG o WebP; elimina el prefijo data-URL del base64. |
INVALID_BODY | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
INVALID_HOST | 403 | Host u origen rechazado | Llama a centeringlab.com desde tu servidor, no desde el navegador de otra web. |
INVALID_HTTP | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
INVALID_IMAGE | 400 | No se puede decodificar la imagen | Envía una imagen raster compatible, preferiblemente JPG, PNG o WebP; elimina el prefijo data-URL del base64. |
INVALID_IMAGE_URL | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
INVALID_INPUT | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
INVALID_JSON | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
INVALID_ORIGIN | 403 | Host u origen rechazado | Llama a centeringlab.com desde tu servidor, no desde el navegador de otra web. |
INVALID_RATIO | 400 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
JSON_REQUIRED | 415 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
MEASURE_QUEUE_FULL | 503 | Servicio saturado | Respeta Retry-After y reintenta con esperas crecientes. |
MEASURE_TIMEOUT | 504 | Tiempo agotado | Usa una imagen menor o un host más rápido; también puedes usar el sitio. |
MEASURE_WORKER_FAILED | 500 | Fallo de servidor o worker | Reintenta con espera, reduce la foto o usa el sitio. |
METHOD_NOT_ALLOWED | 405 | Ruta o método no disponible | Usa los endpoints y métodos documentados. |
NOT_AN_IMAGE | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
NOT_FOUND | 404 | Ruta o método no disponible | Usa los endpoints y métodos documentados. |
RATE_LIMIT_CAPACITY | 503 | Servicio saturado | Respeta Retry-After y reintenta con esperas crecientes. |
RATE_LIMIT_DAY | 429 | Cuota alcanzada | Espera Retry-After (segundos); la cuota diaria se reinicia a medianoche UTC. |
RATE_LIMIT_MINUTE | 429 | Cuota alcanzada | Espera Retry-After (segundos); la cuota diaria se reinicia a medianoche UTC. |
REQUEST_CANCELLED | 499 | Solicitud cancelada | Reintenta si el cliente aún necesita el resultado. |
REQUEST_CAPACITY | 503 | Servicio saturado | Respeta Retry-After y reintenta con esperas crecientes. |
UNSAFE_IMAGE_URL | 400 | URL rechazada o inaccesible | Usa una imagen HTTPS pública en el puerto 443 sin credenciales; revisa DNS, redirecciones y respuesta. |
UNSUPPORTED_ENCODING | 400 / 415 | Solicitud o proporción no válida | Corrige los campos; envía JSON válido sin comprimir. |
UNSUPPORTED_IMAGE | 400 | No se puede decodificar la imagen | Envía una imagen raster compatible, preferiblemente JPG, PNG o WebP; elimina el prefijo data-URL del base64. |
Códigos del detector: HIGH_UNCERTAINTY, NEEDS_REVIEW, LOW_CONFIDENCE, NO_MEASUREMENT, NO_CARD, CARD_TOO_SMALL, CARD_CUT_OFF, NO_PRINTED_BORDER. failed y needs-review no tienen límites de grading. Fotografía la carta completa desde arriba, sin funda, sobre fondo oscuro plano, o usa el editor manual del sitio.
Límites de uso
Cuotas por IP, compartidas con los buckets correspondientes. Grade y standards comparten un minuto; health y OpenAPI otro. Ventanas de minuto fijas y días UTC; sin cuota diaria para llamadas simples/protocolo. Base64 aumenta los bytes y cuenta en el cuerpo JSON: puede impedir usar todo el límite de imagen.
| Límite | Valor actual |
|---|---|
POST /measure · IP | 20 por minuto; 200 por día UTC |
POST /grade + GET /standards · IP | 120 por minuto; Sin cuota diaria en el limitador |
GET /health + GET /openapi.json · IP | 120 por minuto; Sin cuota diaria en el limitador |
Cuerpo JSON | 12 MiB (12582912 bytes) |
Bytes de imagen decodificada | 15 MiB (15728640 bytes) |
Píxeles decodificados (todos los fotogramas) | 40000000 |
Medición, incluida la cola | 15 s |
Descarga de imagen | 10 s |
Mediciones activas | 2 |
Mediciones en cola | 8 |
Solicitudes HTTP en curso | 16 |
Los 429 y 503 de capacidad incluyen Retry-After en segundos. Cola llena y REQUEST_CAPACITY: 5 segundos; capacidad del limitador: 60. Respeta el encabezado con esperas crecientes. Capacidad compartida, sin reserva por cliente ni SLA de disponibilidad o latencia.
Navegador, CORS y privacidad
El navegador de otro sitio recibe 403 INVALID_ORIGIN: usa tu backend. No necesitas clave y añadirla no habilita CORS. Las fotos API llegan al servidor, se procesan solo en memoria y no se guardan en disco; el sitio las procesa localmente. No hay logs por solicitud: solo conteos agregados por endpoint/tool y código de resultado. Consulta privacidad y términos.
MCP y más información
https://centeringlab.com/mcp ofrece las mismas tres herramientas y motor a clientes AI. REST proporciona llamadas HTTP para tu aplicación. Lee AI y MCP, cómo funciona y quiénes somos.
Preguntas sobre la API
¿Es gratuita la API de centrado de cartas para desarrolladores?
Sí. Todos los endpoints son gratuitos, sin cuenta ni planes de pago. Se aplican límites; no autentica cartas ni predice la nota final.
¿Necesitan clave API las integraciones REST?
No. Envía solicitudes válidas desde tu servidor; sigue vigente la restricción de origen del navegador.
¿Cuáles son las cuotas de esta API de centrado?
Medición: 20 por minuto y 200 por día UTC por IP. Grade y standards comparten 120 por minuto por IP. Respeta Retry-After y los límites de tamaño y capacidad.
¿Guarda la API REST las fotografías enviadas?
No. Llegan al servidor y se procesan solo en memoria. Sin logs por solicitud; solo conteos agregados y códigos. El sitio procesa fotos en el dispositivo.
¿Puede otra web llamar directamente desde su navegador?
No. Recibe 403 INVALID_ORIGIN. Llama desde tu backend; no requiere clave API.
¿Qué diferencia hay entre esta API REST y MCP?
REST usa endpoints HTTP; MCP ofrece tres herramientas a clientes AI. Comparten motor y estándares. API y MCP procesan fotos en el servidor; el sitio lo hace localmente.
Centering Lab · Actualizado el