Gratis API voor kaartcentrering: PSA en fotometing
Centering Lab is een gratis REST-API voor kaartcentrering, zonder API-sleutel. Op https://centeringlab.com/api/v1 levert ze fotometingen, verhoudingen en PSA-, BGS-, CGC- of SGC-bovengrenzen op basis van alleen centrering. Ze voorspelt geen eindcijfer en controleert geen echtheid. Roep haar aan vanaf je eigen server. OpenAPI.
Snel beginnen
Voer curl uit in je terminal. Beide voorassen zijn opgegeven, maar de achterkant ontbreekt: incomplete is true. PSA 10 is een centreringsgrens, geen voorspelling van het eindcijfer.
POST /api/v1/grade
Verzoek
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"}'HTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"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 en velden
Bekende verhoudingen
POST /grade vereist minstens één van front_lr, front_tb, back_lr, back_tb. Normalisatie naar de grootste kant. Percentages (55), fracties (0.55) en paren met som 100 (55/45) of 1 (0.55/0.45) zijn geldig. Scheidingstekens: /, -, –, —, :, x en spaties; % mag. De losse waarde 1 is dubbelzinnig en wordt geweigerd. L/R of left/right alleen voor *_lr; T/B of top/bottom voor *_tb.
house filtert PSA, BGS, CGC of SGC. normalizations verklaart fractieconversies. missing_axes, missing_faces en incomplete tonen ontbrekende gegevens die de grens kunnen verlagen. combined combineert zijden; limiting_face en limiting_axis tonen de beperking. Elke grens bevat bronnen en bewijsstatus.
Contractvelden (exacte JSON-namen)
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, disclaimerContractvelden (exacte JSON-namen)
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, verificationFotometing
POST /measure vereist face: front of back. Standaard card_size is standard (63×88 mm); small is 59×86 mm. Geef precies één bron: openbare HTTPS-image_url op poort 443 of ruwe image_base64 zonder data-URL-voorvoegsel. Privéadressen, inloggegevens en antwoorden zonder afbeelding worden geweigerd, ook bij omleidingen. REST aanvaardt ook één openaiFileIdRefs van GPT Actions; gebruik normaal URL of base64. Stuur één rasterframe, liefst JPG, PNG of WebP.
HTTP 200 kan status ok, needs-review of failed bevatten; alleen ok heeft ceilings. Controleer code, confidence, warnings, lr en tb. uncertainty_pp en sigma_pp zijn procentpunten; stations_major_percent bevat steekproeven. Bij onzekerheid: nieuwe foto of controle via adjust_url. Het voorbeeld stuurt bewust een kleine effen afbeelding: NO_CARD is een echte mislukking, geen geslaagde meting.
Contractvelden (exacte JSON-namen)
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
Verzoek
curl --fail-with-body 'https://centeringlab.com/api/v1/measure' \
-H 'Content-Type: application/json' \
--data '{"face":"front","card_size":"standard","image_base64":"iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAACXBIWXMAAAPoAAAD6AG1e1JrAAAAD0lEQVQImWNQwAEYhpYEAGFPGAHjXOFDAAAAAElFTkSuQmCC"}'HTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"status": "failed",
"code": "NO_CARD",
"face": "front",
"card_size": "standard",
"lr": null,
"tb": null,
"confidence": null,
"warnings": [],
"ceilings": null,
"adjust_url": "https://centeringlab.com/"
}Sla je foto op als card.jpg. Dit antwoord gebruikt de demofoto van de website: onzekerheid geeft needs-review en ceilings is null. Je eigen foto geeft eigen metingen.
POST /api/v1/measure
Verzoek
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.jsonHTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"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/"
}Normen en bronnen
GET /standards aanvaardt optionele house en face. official, interpreted en approximate zijn bewijsstatussen, geen nauwkeurigheidsgaranties. bands[].status geldt per band; source, sources, verified en verification geven de herkomst. TAG is uitgesloten. SGC publiceert geen tabel voor achterkantcentrering: de banden zijn leeg en alleen de achterkant geeft geen SGC-grens.
Contractvelden (exacte JSON-namen)
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
Verzoek
curl --fail-with-body 'https://centeringlab.com/api/v1/standards?house=PSA&face=front'HTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"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 en schema
GET /health levert status, naam, versie en disclaimer. GET /openapi.json levert OpenAPI 3.1.0. Het meetschema is bedoeld voor GPT Actions (URL of runtime-bestandsverwijzing); REST aanvaardt ook base64 volgens de velden hierboven.
GET /api/v1/health
Verzoek
curl --fail-with-body 'https://centeringlab.com/api/v1/health'HTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"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
Verzoek
curl --fail-with-body 'https://centeringlab.com/api/v1/openapi.json'HTTP 200-antwoord
Uittreksel uit een echt lokaal HTTP-antwoord; extra velden en banden zijn weggelaten. JSON-sleutels en servermeldingen blijven Engels.
{
"openapi": "3.1.0",
"info": {
"title": "Centering Lab API",
"version": "1.1.2"
},
"servers": [
{
"url": "https://centeringlab.com"
}
]
}JavaScript en Python
Gebruik Node-fetch op de server. Beide voorbeelden sturen hetzelfde startverzoek. Python gebruikt de standaardbibliotheek. Controleer HTTP-fouten en bij metingen ook status ondanks 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))
raiseFouten en opnieuw proberen
HTTP-fouten bevatten status, code, message en disclaimer. De tabel geldt voor REST, zonder MCP-protocolfouten of privéstatistieken. UNSUPPORTED_ENCODING is 415 bij gecomprimeerde JSON en 400 bij gecomprimeerde afbeeldingsantwoorden. Detectorcodes komen met HTTP 200.
| Code | HTTP | Betekenis | Wat te doen |
|---|---|---|---|
BODY_TOO_LARGE | 413 | Te groot | Verminder bytes of pixels; base64 telt mee voor de JSON-body. |
EMPTY_IMAGE | 400 | Afbeelding niet te decoderen | Stuur één ondersteunde rasterafbeelding, liefst JPG, PNG of WebP; verwijder het data-URL-voorvoegsel. |
IMAGE_DNS_FAILED | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
IMAGE_DOWNLOAD_FAILED | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
IMAGE_DOWNLOAD_TIMEOUT | 504 | Tijdslimiet bereikt | Gebruik een kleinere afbeelding of snellere host; gebruik eventueel de website. |
IMAGE_REDIRECT_LIMIT | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
IMAGE_TOO_LARGE | 413 | Te groot | Verminder bytes of pixels; base64 telt mee voor de JSON-body. |
IMAGE_TOO_MANY_PIXELS | 413 | Te groot | Verminder bytes of pixels; base64 telt mee voor de JSON-body. |
INTERNAL_ERROR | 500 | Server- of workerfout | Wacht en probeer opnieuw, verklein de foto of gebruik de website. |
INVALID_ARGUMENTS | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
INVALID_BASE64 | 400 | Afbeelding niet te decoderen | Stuur één ondersteunde rasterafbeelding, liefst JPG, PNG of WebP; verwijder het data-URL-voorvoegsel. |
INVALID_BODY | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
INVALID_HOST | 403 | Host of browseroorsprong geweigerd | Roep centeringlab.com aan vanaf je server, niet vanuit de browser van een andere website. |
INVALID_HTTP | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
INVALID_IMAGE | 400 | Afbeelding niet te decoderen | Stuur één ondersteunde rasterafbeelding, liefst JPG, PNG of WebP; verwijder het data-URL-voorvoegsel. |
INVALID_IMAGE_URL | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
INVALID_INPUT | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
INVALID_JSON | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
INVALID_ORIGIN | 403 | Host of browseroorsprong geweigerd | Roep centeringlab.com aan vanaf je server, niet vanuit de browser van een andere website. |
INVALID_RATIO | 400 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
JSON_REQUIRED | 415 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
MEASURE_QUEUE_FULL | 503 | Dienst vol | Respecteer Retry-After en wacht steeds langer tussen pogingen. |
MEASURE_TIMEOUT | 504 | Tijdslimiet bereikt | Gebruik een kleinere afbeelding of snellere host; gebruik eventueel de website. |
MEASURE_WORKER_FAILED | 500 | Server- of workerfout | Wacht en probeer opnieuw, verklein de foto of gebruik de website. |
METHOD_NOT_ALLOWED | 405 | Route of methode niet beschikbaar | Gebruik de gedocumenteerde endpoints en methoden. |
NOT_AN_IMAGE | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
NOT_FOUND | 404 | Route of methode niet beschikbaar | Gebruik de gedocumenteerde endpoints en methoden. |
RATE_LIMIT_CAPACITY | 503 | Dienst vol | Respecteer Retry-After en wacht steeds langer tussen pogingen. |
RATE_LIMIT_DAY | 429 | Quotum bereikt | Respecteer Retry-After in seconden; het dagquotum herstart om middernacht UTC. |
RATE_LIMIT_MINUTE | 429 | Quotum bereikt | Respecteer Retry-After in seconden; het dagquotum herstart om middernacht UTC. |
REQUEST_CANCELLED | 499 | Verzoek afgebroken | Probeer alleen opnieuw als het resultaat nog nodig is. |
REQUEST_CAPACITY | 503 | Dienst vol | Respecteer Retry-After en wacht steeds langer tussen pogingen. |
UNSAFE_IMAGE_URL | 400 | Afbeeldings-URL geweigerd of onbereikbaar | Gebruik een openbare HTTPS-afbeelding op poort 443 zonder inloggegevens; controleer DNS, omleidingen en antwoord. |
UNSUPPORTED_ENCODING | 400 / 415 | Ongeldig verzoek of verhouding | Corrigeer de velden; stuur geldige, ongecomprimeerde JSON. |
UNSUPPORTED_IMAGE | 400 | Afbeelding niet te decoderen | Stuur één ondersteunde rasterafbeelding, liefst JPG, PNG of WebP; verwijder het data-URL-voorvoegsel. |
Detectorcodes: HIGH_UNCERTAINTY, NEEDS_REVIEW, LOW_CONFIDENCE, NO_MEASUREMENT, NO_CARD, CARD_TOO_SMALL, CARD_CUT_OFF, NO_PRINTED_BORDER. failed en needs-review hebben geen gradinggrenzen. Fotografeer de hele kaart recht van boven, zonder sleeve op een donkere vlakke ondergrond, of gebruik de handmatige website-editor.
Gebruikslimieten
Quota gelden per IP en delen de bijbehorende groepen. Grade en standards delen één minutenteller; health en OpenAPI een andere. Vaste minutenvensters en UTC-dagen; geen dagquotum voor eenvoudige/protocolaanroepen. Base64 vergroot de bytes en telt mee voor JSON: de volledige afbeeldingslimiet past mogelijk niet.
| Limiet | Huidige waarde |
|---|---|
POST /measure · IP | 20 per minuut; 200 per UTC-dag |
POST /grade + GET /standards · IP | 120 per minuut; Geen dagquotum in de limiter |
GET /health + GET /openapi.json · IP | 120 per minuut; Geen dagquotum in de limiter |
JSON-body | 12 MiB (12582912 bytes) |
Gedecodeerde afbeeldingsbytes | 15 MiB (15728640 bytes) |
Gedecodeerde pixels (alle frames) | 40000000 |
Meting inclusief wachtrij | 15 s |
Afbeeldingsdownload | 10 s |
Actieve metingen | 2 |
Metingen in wachtrij | 8 |
Lopende HTTP-verzoeken | 16 |
429 en capaciteits-503 bevatten Retry-After in seconden. Volle meetwachtrij en REQUEST_CAPACITY: 5 seconden; limitercapaciteit: 60. Respecteer de header met steeds langere wachttijd. Gedeelde capaciteit, zonder reservering per client of SLA voor beschikbaarheid en snelheid.
Browser, CORS en privacy
De browser van een andere website krijgt 403 INVALID_ORIGIN: gebruik je backend. Geen sleutel nodig; een sleutel opent CORS niet. API-foto’s gaan naar de server en worden alleen in geheugen verwerkt, zonder schijfopslag. De website verwerkt lokaal. Geen verzoeklogs: alleen geaggregeerde aantallen per endpoint/tool en resultaatcode. Privacy en voorwaarden.
MCP en meer informatie
https://centeringlab.com/mcp biedt AI-clients dezelfde drie tools en engine. REST biedt directe HTTP-aanroepen. Lees AI en MCP, hoe meten werkt en over Centering Lab.
Vragen over de API
Is de kaartcentrerings-API gratis voor ontwikkelaars?
Ja. Alle endpoints zijn gratis, zonder account of betaald plan. Gebruikslimieten gelden; geen echtheidscontrole of voorspelling van een eindcijfer.
Hebben REST-integraties een API-sleutel nodig?
Nee. Stuur geldige verzoeken vanaf je server; de beperking op browseroorsprongen blijft gelden.
Welke quota heeft deze centrerings-API?
Metingen: 20 per minuut en 200 per UTC-dag per IP. Grade en standards delen 120 per minuut per IP. Respecteer Retry-After en grootte- en capaciteitslimieten.
Bewaart de REST-API ingezonden foto’s?
Nee. Ze bereiken de server, maar worden alleen in geheugen verwerkt. Geen verzoeklogs; alleen geaggregeerde aantallen en codes. Websitefoto’s blijven op het apparaat.
Kan een andere website rechtstreeks vanuit de browser aanroepen?
Nee. Dat geeft 403 INVALID_ORIGIN. Gebruik je backend; geen API-sleutel nodig.
Hoe verschilt deze REST-API van MCP?
REST gebruikt HTTP-endpoints; MCP geeft AI-clients drie tools. Dezelfde engine en normen. API/MCP-foto’s gaan naar de server; de website verwerkt lokaal.
Centering Lab · Bijgewerkt op