無料カードセンタリングAPI:PSA・写真測定

Centering Labは無料のカードセンタリングREST APIです。キー不要で、https://centeringlab.com/api/v1から写真の測定値・比率・PSA等の上限を返します。最終点数の予測や真贋鑑定ではありません。サーバーから呼び出してください。OpenAPI。

クイックスタート

端末でcurlを実行します。表面の両軸は指定されていますが裏面がないため、incompleteはtrueです。PSA 10はセンタリングの上限であり、最終点数の予測ではありません。

POST /api/v1/grade

リクエスト

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レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "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."
}

エンドポイントとフィールド

既知の比率

POST /gradeにはfront_lr、front_tb、back_lr、back_tbの少なくとも1つが必要です。大きい側の割合に正規化します。百分率(55)、小数の比率(0.55)、合計100の組(55/45)または合計1の組(0.55/0.45)を使えます。区切りは/、-、–、—、:、x、空白、%は任意。単独の1は曖昧で拒否されます。L/R・left/rightは*_lr、T/B・top/bottomは*_tb専用です。

houseでPSA・BGS・CGC・SGCを絞り込めます。normalizationsは小数の変換を示します。missing_axes、missing_faces、incompleteは不足を示し、未測定の軸や面によって上限は下がる可能性があります。combinedは指定した面を組み合わせ、limiting_faceとlimiting_axisが制約を示します。各上限には出典と根拠区分が付属します。

契約フィールド(正確な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, disclaimer

契約フィールド(正確な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, verification

写真の測定

POST /measureはface(frontまたはback)必須です。card_sizeの初期値はstandard(63×88 mm)、smallは59×86 mm。ポート443の公開HTTPS image_url、またはdata-URLプレフィックスなしのimage_base64のどちらか1つを指定します。プライベートアドレス、認証情報、画像以外の応答は転送先も含め拒否されます。RESTはGPT Actions実行時のopenaiFileIdRefs1件も受け付けます。通常の連携ではURLかbase64を使い、単一フレームのJPG・PNG・WebPなどのラスター画像を送ります。

HTTP 200でもstatusはok、needs-review、failedのいずれかです。ceilingsがあるのはokのみ。code、confidence、warnings、lr、tbを確認してください。uncertainty_ppとsigma_ppはパーセントポイント、stations_major_percentは各測定位置の比率です。不確かな場合は撮り直すかadjust_urlで確認します。例では小さい単色画像を送り、実際にNO_CARDを返しています。成功した測定の例ではありません。

契約フィールド(正確な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, disclaimer

POST /api/v1/measure

リクエスト

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レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "status": "failed",
  "code": "NO_CARD",
  "face": "front",
  "card_size": "standard",
  "lr": null,
  "tb": null,
  "confidence": null,
  "warnings": [],
  "ceilings": null,
  "adjust_url": "https://centeringlab.com/"
}

写真をcard.jpgとして保存します。この応答はサイトのデモ写真を使用した実測です。不確かさによりneeds-reviewとなり、ceilingsはnullです。自分の写真では測定値が変わります。

POST /api/v1/measure

リクエスト

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.json

HTTP 200レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "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/"
}

公開基準と出典

GET /standardsは任意のhouseとfaceを受け付けます。official、interpreted、approximateは根拠区分で、精度保証ではありません。bands[].statusは各基準帯の区分、source、sources、verified、verificationは出典情報です。TAGは対象外。SGCは裏面の公開センタリング表がないため、裏面の基準帯は空で、裏面だけではSGCの上限を定めません。

契約フィールド(正確な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, disclaimer

GET /api/v1/standards?house=PSA&face=front

リクエスト

curl --fail-with-body 'https://centeringlab.com/api/v1/standards?house=PSA&face=front'

HTTP 200レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "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."
}

稼働状態とスキーマ

GET /healthは状態、名前、バージョン、免責文を返します。GET /openapi.jsonはOpenAPI 3.1.0を返します。測定入力スキーマはGPT Actions向け(URLまたは実行時ファイル参照)ですが、RESTは上記のフィールドに従うbase64も受け付けます。

GET /api/v1/health

リクエスト

curl --fail-with-body 'https://centeringlab.com/api/v1/health'

HTTP 200レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "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

リクエスト

curl --fail-with-body 'https://centeringlab.com/api/v1/openapi.json'

HTTP 200レスポンス

ローカルサーバーの実際のHTTP応答から抜粋。省略したフィールドや他の基準帯は表示していません。JSONキーとサーバーメッセージは英語のままです。

{
  "openapi": "3.1.0",
  "info": {
    "title": "Centering Lab API",
    "version": "1.1.2"
  },
  "servers": [
    {
      "url": "https://centeringlab.com"
    }
  ]
}

JavaScriptとPython

Nodeのfetchはサーバー側で使います。両例はクイックスタートと同じリクエストです。Pythonは標準ライブラリを使います。HTTPエラーと、測定時はHTTP 200でもstatusを確認してください。

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))
    raise

エラーと再試行

HTTPエラーはstatus、code、message、disclaimerを含みます。表はREST用で、MCPプロトコルや非公開統計のエラーは含みません。UNSUPPORTED_ENCODINGは圧縮JSONで415、圧縮画像応答で400です。検出器のコードはHTTP 200で返されます。

コードHTTP意味対処方法
BODY_TOO_LARGE413サイズ制限超過バイト数またはピクセル数を減らしてください。base64はJSON本文の制限にも含まれます。
EMPTY_IMAGE400画像をデコードできない対応する単一のラスター画像を送信し、base64のdata-URLプレフィックスを削除してください。
IMAGE_DNS_FAILED400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
IMAGE_DOWNLOAD_FAILED400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
IMAGE_DOWNLOAD_TIMEOUT504時間制限超過小さい画像か高速な画像ホストを使うか、サイトで測定してください。
IMAGE_REDIRECT_LIMIT400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
IMAGE_TOO_LARGE413サイズ制限超過バイト数またはピクセル数を減らしてください。base64はJSON本文の制限にも含まれます。
IMAGE_TOO_MANY_PIXELS413サイズ制限超過バイト数またはピクセル数を減らしてください。base64はJSON本文の制限にも含まれます。
INTERNAL_ERROR500サーバーまたはワーカーのエラー時間を置いて再試行するか、写真を縮小するか、サイトを使ってください。
INVALID_ARGUMENTS400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
INVALID_BASE64400画像をデコードできない対応する単一のラスター画像を送信し、base64のdata-URLプレフィックスを削除してください。
INVALID_BODY400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
INVALID_HOST403ホストまたはブラウザのオリジンを拒否別サイトのブラウザではなく、自分のサーバーからcenteringlab.comにアクセスしてください。
INVALID_HTTP400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
INVALID_IMAGE400画像をデコードできない対応する単一のラスター画像を送信し、base64のdata-URLプレフィックスを削除してください。
INVALID_IMAGE_URL400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
INVALID_INPUT400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
INVALID_JSON400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
INVALID_ORIGIN403ホストまたはブラウザのオリジンを拒否別サイトのブラウザではなく、自分のサーバーからcenteringlab.comにアクセスしてください。
INVALID_RATIO400入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
JSON_REQUIRED415入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
MEASURE_QUEUE_FULL503サービスの処理枠が満杯Retry-Afterを守り、待機時間を増やして再試行してください。
MEASURE_TIMEOUT504時間制限超過小さい画像か高速な画像ホストを使うか、サイトで測定してください。
MEASURE_WORKER_FAILED500サーバーまたはワーカーのエラー時間を置いて再試行するか、写真を縮小するか、サイトを使ってください。
METHOD_NOT_ALLOWED405パスまたはメソッドが無効記載されたエンドポイントとメソッドを使ってください。
NOT_AN_IMAGE400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
NOT_FOUND404パスまたはメソッドが無効記載されたエンドポイントとメソッドを使ってください。
RATE_LIMIT_CAPACITY503サービスの処理枠が満杯Retry-Afterを守り、待機時間を増やして再試行してください。
RATE_LIMIT_DAY429利用回数の上限Retry-Afterの秒数を待ってください。日次枠はUTCの午前0時にリセットされます。
RATE_LIMIT_MINUTE429利用回数の上限Retry-Afterの秒数を待ってください。日次枠はUTCの午前0時にリセットされます。
REQUEST_CANCELLED499リクエスト取消結果がまだ必要な場合のみ再試行してください。
REQUEST_CAPACITY503サービスの処理枠が満杯Retry-Afterを守り、待機時間を増やして再試行してください。
UNSAFE_IMAGE_URL400画像URLが拒否されたか到達不能認証情報なしの公開HTTPS画像をポート443で指定し、DNSと転送先を確認してください。
UNSUPPORTED_ENCODING400 / 415入力または比率が無効フィールドを修正し、圧縮していない有効なJSONを送信してください。
UNSUPPORTED_IMAGE400画像をデコードできない対応する単一のラスター画像を送信し、base64のdata-URLプレフィックスを削除してください。

検出器のコード:HIGH_UNCERTAINTY, NEEDS_REVIEW, LOW_CONFIDENCE, NO_MEASUREMENT, NO_CARD, CARD_TOO_SMALL, CARD_CUT_OFF, NO_PRINTED_BORDER。failedとneeds-reviewに鑑定上限はありません。スリーブを外し、暗い平らな背景でカード全体を真上から撮るか、サイトの手動エディターを使ってください。

利用制限

制限はIP単位で、対応する処理グループと共有します。gradeとstandardsは毎分の枠を共有し、healthとOpenAPIは別の枠です。固定の分区間とUTCの日付境界を使います。簡易・プロトコル呼び出しの日次枠はありません。base64でバイト数が増え、JSON本文の枠にも含まれるため、画像上限すべてを使えない場合があります。

制限現在の値
POST /measure · IP20 毎分; 200 UTCの1日あたり
POST /grade + GET /standards · IP120 毎分; リミッターに1日の制限なし
GET /health + GET /openapi.json · IP120 毎分; リミッターに1日の制限なし
JSON本文12 MiB (12582912 bytes)
デコード後の画像バイト数15 MiB (15728640 bytes)
デコード後の総ピクセル数40000000
待機を含む測定時間15 s
画像ダウンロード10 s
同時測定2
待機測定8
処理中のHTTPリクエスト16

429と処理枠の503は秒単位のRetry-Afterを含みます。測定待機列満杯とREQUEST_CAPACITYは5秒、リミッター容量は60秒。ヘッダーを守り、間隔を増やして再試行します。容量はサービス全体で共有し、個別予約はありません。可用性・応答時間のSLAは約束しません。

ブラウザ・CORS・プライバシー

他サイトのブラウザからは403 INVALID_ORIGIN。自分のバックエンドから呼び出します。APIキーは不要で、キーを追加してもCORSは開放されません。API画像はサーバーでメモリ内処理のみを行い、ディスクに保存しません。サイトは端末内で処理します。リクエスト単位のログはなく、エンドポイント・ツールと結果コード別の集計のみです。プライバシーと利用規約を確認してください。

MCPと関連情報

https://centeringlab.com/mcpはAIクライアントに同じ3つのツールと測定エンジンを提供します。RESTはアプリ向けの直接HTTP呼び出しです。AI・MCP設定、測定方法、Centering Labについても参照してください。

APIのよくある質問

開発者向けカードセンタリングAPIは無料ですか?

はい。全エンドポイントが無料で、アカウントや有料プランは不要です。利用制限はあります。真贋鑑定や最終点数の予測は行いません。

REST連携にAPIキーは必要ですか?

不要です。サーバーから有効なリクエストを送信してください。ブラウザのオリジン制限は適用されます。

センタリングAPIの利用回数制限は?

写真測定はIPごとに毎分20回、UTCの1日200回です。gradeとstandardsは毎分120回を共有します。Retry-Afterとサイズ・容量の制限を守ってください。

REST APIは送信した写真を保存しますか?

保存しません。サーバーには届きますがメモリ内だけで処理します。個別ログはなく、利用数と結果コードの集計のみです。サイトの写真は端末内で処理します。

他サイトのブラウザから直接APIを呼べますか?

できません。403 INVALID_ORIGINになります。APIキー不要の自分のバックエンドから呼び出してください。

REST APIとMCPの違いは何ですか?

RESTはHTTPエンドポイント、MCPはAIクライアント向けの3つのツールです。エンジンと基準は同じです。API/MCPはサーバー、サイトは端末内で画像を処理します。