Bezpłatne API centrowania kart: PSA i pomiar zdjęć
Centering Lab to bezpłatne REST API centrowania kart, bez klucza API. Pod https://centeringlab.com/api/v1 zwraca pomiary zdjęć, proporcje oraz limity PSA, BGS, CGC i SGC wynikające wyłącznie z centrowania. Nie przewiduje oceny końcowej ani nie potwierdza autentyczności kart. Wywołuj je ze swojego serwera. Zdjęcia API trafiają na serwer. OpenAPI.
Szybki start
Uruchom curl w terminalu. Podano obie osie przodu, ale brak tyłu: incomplete ma wartość true. PSA 10 to limit centrowania, nie przewidywanie oceny końcowej.
POST /api/v1/grade
Żądanie
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"}'Odpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"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."
}Endpointy i pola
Znane proporcje
POST /grade wymaga przynajmniej jednego z front_lr, front_tb, back_lr, back_tb. Normalizuje do większej strony. Obsługuje procenty (55), ułamki (0.55) i pary sumujące się do 100 (55/45) lub 1 (0.55/0.45). Separatory: /, -, –, —, :, x i spacje; % opcjonalnie. Pojedyncze 1 jest niejednoznaczne i odrzucane. L/R lub left/right tylko dla *_lr; T/B lub top/bottom tylko dla *_tb.
house filtruje PSA, BGS, CGC lub SGC. normalizations wskazuje przeliczenia ułamków. missing_axes, missing_faces i incomplete oznaczają braki, które mogą obniżyć limit. combined łączy strony; limiting_face i limiting_axis wskazują ograniczenie. Każdy limit zawiera źródła i status dowodów.
Pola kontraktu (dokładne nazwy JSON)
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, disclaimerPola kontraktu (dokładne nazwy JSON)
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, verificationPomiar zdjęcia
POST /measure wymaga face: front lub back. Domyślny card_size to standard (63×88 mm); small to 59×86 mm. Dokładnie jedno źródło: publiczny HTTPS image_url na porcie 443 albo image_base64 bez prefiksu data-URL. Prywatne adresy, dane logowania i odpowiedzi niebędące obrazem są odrzucane także w przekierowaniach. REST akceptuje też jeden openaiFileIdRefs od runtime GPT Actions; zwykłe integracje korzystają z URL lub base64. Wyślij pojedynczą klatkę rastrową, najlepiej JPG, PNG lub WebP.
HTTP 200 może mieć status ok, needs-review lub failed; tylko ok zawiera ceilings. Sprawdź code, confidence, warnings, lr i tb. uncertainty_pp i sigma_pp są w punktach procentowych; stations_major_percent zawiera próbki. Przy niepewności zrób nowe zdjęcie lub sprawdź adjust_url. Przykład celowo wysyła mały jednolity obraz: NO_CARD to rzeczywista porażka, nie udany pomiar.
Pola kontraktu (dokładne nazwy JSON)
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
Żądanie
curl --fail-with-body 'https://centeringlab.com/api/v1/measure' \
-H 'Content-Type: application/json' \
--data '{"face":"front","card_size":"standard","image_base64":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAD0lEQVQImWNQwAEYhpYEAGFPGAHjXOFDAAAAAElFTkSuQmCC"}'Odpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"status": "failed",
"code": "NO_CARD",
"face": "front",
"card_size": "standard",
"lr": null,
"tb": null,
"confidence": null,
"warnings": [],
"ceilings": null,
"adjust_url": "https://centeringlab.com/"
}Zapisz zdjęcie jako card.jpg. Ta odpowiedź używa zdjęcia demonstracyjnego strony: niepewność powoduje needs-review, a ceilings to null. Twoje zdjęcie da własne pomiary.
POST /api/v1/measure
Żądanie
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.jsonOdpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"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/"
}Standardy i źródła
GET /standards przyjmuje opcjonalne house i face. official, interpreted i approximate opisują dowody, nie gwarancje dokładności. bands[].status dotyczy progu; source, sources, verified i verification podają pochodzenie. TAG jest wykluczony. SGC nie publikuje tabeli centrowania tyłu: progi są puste, a sam tył nie określa limitu SGC.
Pola kontraktu (dokładne nazwy JSON)
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
Żądanie
curl --fail-with-body 'https://centeringlab.com/api/v1/standards?house=PSA&face=front'Odpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"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."
}Stan i schemat
GET /health zwraca stan, nazwę, wersję i disclaimer. GET /openapi.json zwraca OpenAPI 3.1.0. Schemat pomiaru służy GPT Actions (URL lub referencja pliku runtime); REST przyjmuje też base64 według pól powyżej.
GET /api/v1/health
Żądanie
curl --fail-with-body 'https://centeringlab.com/api/v1/health'Odpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"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
Żądanie
curl --fail-with-body 'https://centeringlab.com/api/v1/openapi.json'Odpowiedź HTTP 200
Fragment rzeczywistej lokalnej odpowiedzi HTTP; pominięto pola i dodatkowe progi. Klucze JSON i komunikaty serwera pozostają po angielsku.
{
"openapi": "3.1.0",
"info": {
"title": "Centering Lab API",
"version": "1.1.2"
},
"servers": [
{
"url": "https://centeringlab.com"
}
]
}JavaScript i Python
Używaj fetch w Node po stronie serwera. Przykłady wysyłają żądanie ze szybkiego startu. Python korzysta z biblioteki standardowej. Sprawdzaj błędy HTTP oraz status pomiaru także przy 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))
raiseBłędy i ponawianie
Błędy HTTP zawierają status, code, message i disclaimer. Tabela obejmuje REST, bez błędów protokołu MCP i prywatnych statystyk. UNSUPPORTED_ENCODING to 415 dla skompresowanego JSON i 400 dla skompresowanej odpowiedzi obrazu. Kody detektora przychodzą z HTTP 200.
| Kod | HTTP | Znaczenie | Co zrobić |
|---|---|---|---|
BODY_TOO_LARGE | 413 | Przekroczony rozmiar | Zmniejsz bajty lub piksele; base64 wlicza się w limit treści JSON. |
EMPTY_IMAGE | 400 | Nie można zdekodować obrazu | Wyślij pojedynczy obsługiwany raster, najlepiej JPG, PNG lub WebP; usuń prefiks data-URL z base64. |
IMAGE_DNS_FAILED | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
IMAGE_DOWNLOAD_FAILED | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
IMAGE_DOWNLOAD_TIMEOUT | 504 | Przekroczony czas | Użyj mniejszego obrazu lub szybszego hosta; ewentualnie skorzystaj ze strony. |
IMAGE_REDIRECT_LIMIT | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
IMAGE_TOO_LARGE | 413 | Przekroczony rozmiar | Zmniejsz bajty lub piksele; base64 wlicza się w limit treści JSON. |
IMAGE_TOO_MANY_PIXELS | 413 | Przekroczony rozmiar | Zmniejsz bajty lub piksele; base64 wlicza się w limit treści JSON. |
INTERNAL_ERROR | 500 | Błąd serwera lub workera | Poczekaj, zmniejsz zdjęcie lub użyj strony. |
INVALID_ARGUMENTS | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
INVALID_BASE64 | 400 | Nie można zdekodować obrazu | Wyślij pojedynczy obsługiwany raster, najlepiej JPG, PNG lub WebP; usuń prefiks data-URL z base64. |
INVALID_BODY | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
INVALID_HOST | 403 | Odrzucony host lub origin | Wywołuj centeringlab.com ze swojego serwera, nie z przeglądarki innej strony. |
INVALID_HTTP | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
INVALID_IMAGE | 400 | Nie można zdekodować obrazu | Wyślij pojedynczy obsługiwany raster, najlepiej JPG, PNG lub WebP; usuń prefiks data-URL z base64. |
INVALID_IMAGE_URL | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
INVALID_INPUT | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
INVALID_JSON | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
INVALID_ORIGIN | 403 | Odrzucony host lub origin | Wywołuj centeringlab.com ze swojego serwera, nie z przeglądarki innej strony. |
INVALID_RATIO | 400 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
JSON_REQUIRED | 415 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
MEASURE_QUEUE_FULL | 503 | Usługa zajęta | Przestrzegaj Retry-After i zwiększaj odstępy między próbami. |
MEASURE_TIMEOUT | 504 | Przekroczony czas | Użyj mniejszego obrazu lub szybszego hosta; ewentualnie skorzystaj ze strony. |
MEASURE_WORKER_FAILED | 500 | Błąd serwera lub workera | Poczekaj, zmniejsz zdjęcie lub użyj strony. |
METHOD_NOT_ALLOWED | 405 | Niedostępna ścieżka lub metoda | Użyj opisanych endpointów i metod. |
NOT_AN_IMAGE | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
NOT_FOUND | 404 | Niedostępna ścieżka lub metoda | Użyj opisanych endpointów i metod. |
RATE_LIMIT_CAPACITY | 503 | Usługa zajęta | Przestrzegaj Retry-After i zwiększaj odstępy między próbami. |
RATE_LIMIT_DAY | 429 | Wyczerpany limit żądań | Poczekaj Retry-After sekund; limit dzienny odnawia się o północy UTC. |
RATE_LIMIT_MINUTE | 429 | Wyczerpany limit żądań | Poczekaj Retry-After sekund; limit dzienny odnawia się o północy UTC. |
REQUEST_CANCELLED | 499 | Anulowane żądanie | Ponów tylko jeśli wynik jest nadal potrzebny. |
REQUEST_CAPACITY | 503 | Usługa zajęta | Przestrzegaj Retry-After i zwiększaj odstępy między próbami. |
UNSAFE_IMAGE_URL | 400 | URL odrzucony lub niedostępny | Użyj publicznego obrazu HTTPS na porcie 443 bez danych logowania; sprawdź DNS, przekierowania i odpowiedź. |
UNSUPPORTED_ENCODING | 400 / 415 | Nieprawidłowe żądanie lub proporcja | Popraw pola; wyślij prawidłowy nieskompresowany JSON. |
UNSUPPORTED_IMAGE | 400 | Nie można zdekodować obrazu | Wyślij pojedynczy obsługiwany raster, najlepiej JPG, PNG lub WebP; usuń prefiks data-URL z base64. |
Kody detektora: HIGH_UNCERTAINTY, NEEDS_REVIEW, LOW_CONFIDENCE, NO_MEASUREMENT, NO_CARD, CARD_TOO_SMALL, CARD_CUT_OFF, NO_PRINTED_BORDER. failed i needs-review nie zawierają limitów gradingu. Fotografuj całą kartę z góry, bez koszulki, na ciemnej płaskiej powierzchni albo użyj ręcznego edytora strony.
Limity użycia
Limity są na IP, współdzielone w odpowiednich grupach. Grade i standards dzielą licznik minutowy; health i OpenAPI drugi. Stałe okna minutowe i dni UTC; brak limitu dziennego dla prostych/protokolarnych wywołań. Base64 zwiększa bajty i wlicza się w JSON: cały limit obrazu może się nie zmieścić.
| Limit | Aktualna wartość |
|---|---|
POST /measure · IP | 20 na minutę; 200 na dzień UTC |
POST /grade + GET /standards · IP | 120 na minutę; Brak limitu dziennego w limiterze |
GET /health + GET /openapi.json · IP | 120 na minutę; Brak limitu dziennego w limiterze |
Treść JSON | 12 MiB (12582912 bytes) |
Bajty zdekodowanego obrazu | 15 MiB (15728640 bytes) |
Zdekodowane piksele (wszystkie klatki) | 40000000 |
Pomiar wraz z kolejką | 15 s |
Pobieranie obrazu | 10 s |
Aktywne pomiary | 2 |
Pomiary w kolejce | 8 |
Trwające żądania HTTP | 16 |
429 i 503 pojemności zawierają Retry-After w sekundach. Pełna kolejka pomiaru i REQUEST_CAPACITY: 5 sekund; pojemność limitera: 60. Przestrzegaj nagłówka, zwiększając przerwy. Pojemność współdzielona bez rezerwacji dla klienta i bez SLA dostępności lub czasu odpowiedzi.
Przeglądarka, CORS i prywatność
Przeglądarka innej strony dostaje 403 INVALID_ORIGIN: użyj backendu. Klucz nie jest potrzebny i nie otwiera CORS. Zdjęcia API trafiają na serwer, są przetwarzane tylko w pamięci i nie trafiają na dysk. Strona przetwarza lokalnie. Brak logów pojedynczych żądań: tylko zagregowane liczniki według endpointu/tool i kodu wyniku. Prywatność i regulamin.
MCP i dalsze informacje
https://centeringlab.com/mcp daje klientom AI te same trzy narzędzia i silnik. REST oferuje bezpośrednie wywołania HTTP. Zobacz AI i MCP, jak działa pomiar i o Centering Lab.
Pytania o API
Czy API centrowania kart jest bezpłatne dla programistów?
Tak. Wszystkie endpointy są bezpłatne, bez konta i płatnego planu. Obowiązują limity; API nie potwierdza autentyczności ani nie przewiduje oceny końcowej.
Czy integracje REST potrzebują klucza API?
Nie. Wysyłaj prawidłowe żądania ze swojego serwera; ograniczenie origin przeglądarki nadal obowiązuje.
Jakie limity ma to API centrowania?
Pomiar: 20 na minutę i 200 na dzień UTC na IP. Grade i standards dzielą 120 na minutę na IP. Przestrzegaj Retry-After oraz limitów rozmiaru i pojemności.
Czy REST API zapisuje przesłane zdjęcia?
Nie. Trafiają na serwer, ale są przetwarzane tylko w pamięci. Brak logów żądań, tylko zagregowane liczniki i kody. Zdjęcia strony zostają na urządzeniu.
Czy inna strona może wywołać API bezpośrednio z przeglądarki?
Nie. Otrzyma 403 INVALID_ORIGIN. Wywołuj ze swojego backendu, bez klucza API.
Czym różni się to REST API od MCP?
REST używa endpointów HTTP; MCP oferuje trzy narzędzia klientom AI. Wspólny silnik i standardy. API/MCP przetwarzają zdjęcia na serwerze, strona lokalnie.
Centering Lab · Aktualizacja