Hosted REST API · alpha

Apostille インテグレーションを構築する。

agent を登録し、明示的に認可された statement を送信して、ポータブルな certificate を取得します。元のファイルと private key はアプリケーション内に保持されます。

REST API base URLhttps://ifandonlyif.io/api/apostille/v1

public request から始める

status endpoint に token は不要です。発行前に enabled を確認し、workspace の上限は limits から読みます。

curl --fail-with-body --silent --show-error \
  https://ifandonlyif.io/api/apostille/v1/status

これは hosted REST API です。公開 MCP は別の読み取り専用インターフェースです(後述)。

administrator key で認証する

GET /status の protocols に Core 0.3 がある場合は、ML-DSA-65 の administrator key を使います。初回ログインで private workspace が作成され、以後は同じものが返されます。Ed25519 key でログインできるのは、既存の Core 0.1 workspace(読み取り専用)のみです。パスワード、OAuth、account recovery はありません。

  1. administrator public_key(Ed25519 は 32 bytes、ML-DSA-65 は 1952 bytes、unpadded base64url)で challenge を要求します。response は challenge_id、issuer、message、expires_at(5 分)を返します。
  2. 設定済みの issuer、key の fingerprint、返された UUID v4 の challenge_id、canonical UTC の expires_at から下記の message を末尾の改行なしで再構成します。有効期限が 7 分以内のものだけを受け入れます。
  3. UTF-8 の message をそのままローカルで署名します(Core 0.1 は Ed25519、Core 0.3 は ML-DSA-65)。challenge_id、message、unpadded-base64url の signature を /auth/verify に POST します。challenge は一度きりで、private key は送りません。
  4. 管理者の access_token はメモリに保持し、Authorization: Bearer <access_token> として owner routes にだけ送ります。有効期間は 900 秒で、期限後は新しい challenge でログインします。管理者 session や署名鍵を CI に渡さないでください。
iff-apostille/login/0.1
issuer:https://ifandonlyif.io/apostille
key_id:<administrator_key_id>
challenge:<challenge_id>
expires_at:<expires_at>
purpose:register_or_login

key_id は sha256: に続けて、生の public key の SHA-256 を小文字 hex にしたものです。この message は artifact の署名ではありません。

CI 用の読み取り専用認証情報

API プレビューです。利用可否はデプロイ環境によって異なります。使用前に対象サービスの /status で enabled: true、features の supply_chain_releases と supply_chain_ci_credentials、および実際のエンドポイントの利用可否を確認してください。

不透明な CI bearer は、単一の workspace、完全一致する product と policy label に限定されます。その範囲の release 取得、現在の policy 取得、メタデータ評価だけが可能です。他の owner routes は拒否します。最新 policy version と独立に選択した issuer/producer pins は引き続き必要です。

Core 0.3 管理者 session と署名付き create_release_credential 操作で作成します。有効期限は明示し、最大 90 日(推奨 30 日)です。scope に wildcard はなく変更できません。token は初回だけ返り、再試行は metadata のみです。owner session で一覧取得・失効ができます。各リクエストで期限と失効を確認しますが、処理中のリクエストは完了する場合があります。

Core バージョンと hosted Core 0.3

ホスト型 service が発行するのは、GET /status の protocols に挙がる Core 0.3(ML-DSA-65)のみです。Core 0.1 と 0.2 の record は引き続き検証できます(verification_protocols)。耐量子なのは Core 0.3 の署名のみで、service 全体ではありません。SHA-256 digest により衝突耐性は NIST category 2 に留まります。ホスト型 issuer の pin は公開 repository の HOSTED_KEYS.md にあります。

  • GET /keys は Core 0.1 の directory を返します。過去の bundle を検証するための legacy Ed25519 key、未設定なら空の keys です。GET /keys?protocol=<URL エンコードした完全な identifier> はそのバージョンの directory(protocol、issuer、key_id・public_key・algorithm を持つ keys[]、trust)を返します。Core 0.3 の key は ML-DSA-65 で、public key は 2603 文字です。Core 0.2 を含む未知または非対応のバージョンは 400 unsupported_protocol_version です。
  • ML-DSA-65(2603 文字)の key は、1 行目を iff-apostille/login/0.3 にした login message を使います(下記)。pure ML-DSA-65・空の context で署名します(signature は 4412 文字)。Ed25519(43 文字)の key は Core 0.1 の login message を使い、既存の Core 0.1 workspace にのみログインできます。workspace のない key の有効な署名は 410 core_0_1_retired です。ML-DSA key で Core 0.1 の login に fallback してはいけません。
iff-apostille/login/0.3
issuer:https://ifandonlyif.io/apostille
key_id:<administrator_key_id>
challenge:<challenge_id>
expires_at:<expires_at>
purpose:register_or_login

異なるのは 1 行目だけです。key_id は sha256: に続けて、生の ML-DSA-65 public key の SHA-256 を小文字 hex にしたものです。

  • workspace の Core バージョンは administrator key のアルゴリズムで決まります。新しい workspace は Core 0.3(ML-DSA-65)です。既存の Core 0.1(Ed25519)workspace は読み取り専用で、参照、ダウンロード、profile 編集、失効、release policy の更新・撤回・評価は使えます。登録、発行、ERC-8004 binding は 410 core_0_1_retired です。Core 0.2 は 400 unsupported_protocol_version です。
  • ML-DSA-65 の administrator key は専用の workspace を開きます。Core 0.1 workspace は移行されず、その agent、certificate、profile は Ed25519 key に残ります。
  • バージョンは両方向で確認します。grant の protocol は statement と、返された bundle の protocol は送信したものと一致させます。新しい certificate には Core 0.3 の issuer key を、過去のものには Core 0.1 の key を pin します。

publication ごとに個別に認可する

ログインは publication を認可しません。署名付き envelope は Core SDK または CLI で作成し、独自の serialization は作らないでください。

  1. administrator が delegation に、agent が acceptance に署名します。どちらも同じ agent と service audience に紐付けます。POST /agents で登録します。
  2. 原本をローカルで hash し、agent が署名した origin-statement を作成します。原本の選択と保管はアプリケーションの責任です。
  3. administrator が、statement digest、audience、nonce、private/public visibility を結び付けた別の publication grant に署名します。/submissions には statement と grant だけを POST します。login token で grant の代わりにはできません。
  4. 公開範囲は署名付き grant で決まります。public grant は、署名済み bundle 全体(関連付け可能な key、識別子、timestamp、digest、size)の配布を認可しますが、workspace profile は対象外です。
  5. bundle をダウンロードし、独立して選んだ issuer/key pin でローカル検証します。API が返す key が自動的に信頼されることはありません。

Endpoint リファレンス

path は REST base URL からの相対パスで、GET は HEAD にも対応します。owner routes は管理者 session を使用し、下記の読み取り/評価 3 routes だけが scoped CI にも対応します。public routes は token 不要で、公開 release は public_id を使用します。

フィールド一覧は response の形を示すもので、そのまま使える JSON ではありません。version と size は十進文字列です。

GET /status

Public

issuer、発行する protocols、検証できる verification_protocols、availability、limits を読み取ります。legacy の protocol は Core 0.1 の identifier です。計画中の provider 名は、有効な identity check ではありません。

Request fields
Request body なし
Response fields / type
protocol (legacy: the Core 0.1 identifier), protocols[] (full identifiers the service issues; absent on a service that predates it), verification_protocols[] (full identifiers it verifies), issuer, enabled, limits {max_agents, max_daily_certificates}, features[] (supply_chain_releases advertises release API support; supply_chain_ci_credentials advertises scoped CI credentials; check enabled separately; ml_dsa_65_keys when Core 0.3 is enabled; core_0_1_issuance_retired), planned[]
Success HTTP status
200

GET /keys

Public

issuer の public key と fingerprint を読み取ります。?protocol=<完全な identifier> でその Core バージョンの directory を選べます。directory は参照先であり、trust root ではありません。

Request fields
protocol (query, optional): full identifier, URL-encoded
Response fields / type
protocol, issuer, keys[] {key_id, public_key, algorithm}, trust
Success HTTP status
200

POST /auth/challenges

Public

短命な login challenge を作成します。同じ key の未使用 challenge が 6 件目になると、最も古いものが無効になります。

Request fields
public_key: string (Ed25519, 43 characters; or ML-DSA-65, 2603 characters)
Response fields / type
challenge_id, message, expires_at, issuer
Success HTTP status
201

POST /auth/verify

Public

challenge を消費して 15 分の session を受け取ります。期限切れ、改ざん、再送された proof は拒否されます。

Request fields
challenge_id: string, message: string, signature: string (Ed25519, or ML-DSA-65 with 4412 characters)
Response fields / type
access_token, token_type, expires_in, workspace: Workspace
Success HTTP status
200

GET /me

Owner

自分の workspace、agent records、最近の certificates を読み取ります。この alpha に pagination はありません。

Request fields
Request body なし
Response fields / type
workspace: Workspace, agents: Agent[], certificates: Certificate[]
Success HTTP status
200

PUT /workspace

Owner

workspace 名と public profile の公開設定を更新します。certificate は公開されず、profile は自己申告です。

Request fields
name: string, is_public: boolean
Response fields / type
Workspace
Success HTTP status
200

POST /agents

Owner

有効な delegation と acceptance を登録します。同一で認可済みの replay には元の record を返します。Core 0.3 のみ。Core 0.1 の request や workspace は 410 core_0_1_retired です。

Request fields
name: string, delegation: Envelope, acceptance: Envelope
Response fields / type
Agent
Success HTTP status
201 / 200

POST /agents/{id}/revoke

Owner

agent の新規発行を取り消せない形で revoke します。発行済みの署名付き bytes は変わらず、offline verification では revoke を確認できません。

Request fields
Request body なし
Response fields / type
Agent (revoked_at)
Success HTTP status
200

POST /submissions

Owner

agent、statement、別の publication grant を検証して origin certificate を発行します。同一の retry でも有効な authorization が必要です。Core 0.3 のみ。Core 0.1 の request や workspace は 410 core_0_1_retired です。

Request fields
statement: Envelope, grant: Envelope
Response fields / type
Certificate (id, workspace_id, agent_id, public_id, idempotency_key, body_hash, bundle, is_public, created_at)
Success HTTP status
201 / 200

GET /certificates/{id}/bundle

Owner

署名付き Bundle そのものをダウンロードします。他の workspace は取得できません。

Request fields
Request body なし
Response fields / type
Bundle
Success HTTP status
200

POST /certificates/{id}/hide

Owner

certificate と、それに依存する release の公開配信を停止します。復元やダウンロード済みコピーの削除はできません。release の撤回とは別です。

Request fields
Request body なし
Response fields / type
id, is_public: false
Success HTTP status
200

GET /public/certificates/{public_id}

Public

public_id で、明示的に公開された certificate を読み取ります(非公開・非表示は 404)。原本ファイルは提供しません。

Request fields
Request body なし
Response fields / type
public_id, bundle: Bundle, created_at
Success HTTP status
200

GET /public/organizations/{public_id}

Public

public_id で、明示的に公開された workspace profile を読み取ります。self_declared と明記され、key や非公開フィールドは含みません。

Request fields
Request body なし
Response fields / type
profile {public_id, name, created_at}, organization_binding: self_declared
Success HTTP status
200

GET /erc8004/config

Public

ERC-8004 binding が有効か、どの registry に対応するか、発行する binding profile(profiles。profile は legacy の 0.1 identifier)を読み取ります。Public です。

Request fields
Request body なし
Response fields / type
profile (legacy: the 0.1 identifier), profiles[] (binding profiles the service issues), enabled, networks[] {chain_id, registry_address}, max_binding_age_seconds, wallet_support
Success HTTP status
200

POST /agents/{id}/erc8004

Owner

administrator 署名の binding request と EOA owner の EIP-191 署名を送信します。private で immutable な issuer_checked snapshot を返し、チェーン取引は送信しません。Core 0.3 の workspace には binding 0.3 を発行し、binding 0.1 は 410 core_0_1_retired です。

Request fields
request: Envelope, owner_signature: string (0x + 130 lowercase hex characters)
Response fields / type
id, agent_id, document, created_at, expires_at
Success HTTP status
201 / 200

GET /agents/{id}/erc8004

Owner

最新の private binding snapshot を取得します(他の workspace は 404)。issuer が finalized block 1 点で観測した ownership の記録で、現在の ownership や payment authority は証明しません。

Request fields
Request body なし
Response fields / type
id, agent_id, document, created_at, expires_at
Success HTTP status
200

POST /releases

Owner

API preview:/status で enabled: true と features の supply_chain_releases が必要です。certificate が対象とする canonical release manifest を、別の administrator 署名の承認とともに登録します。binary やソースはアップロードしません。Core 0.1 の workspace や certificate は 410 core_0_1_retired です。

Request fields
certificate_id: string, manifest_base64: string, visibility: private | public, authorization: {payload_base64, statement: Envelope}
Response fields / type
Release
Success HTTP status
201 / 200

GET /releases/{id}

Owner

自分の release manifest、certificate bundle、現在の hosted status を取得します。owner session または同じ workspace の完全一致 product に限定された CI credential を受け付けます。有効な署名だけでは現在のデプロイ許可になりません。

Request fields
Request body なし
Response fields / type
release: Release, bundle: Bundle, current_status: {state, withdrawn_at, reason, agent_state, as_of, basis, offline_proof: false, issuer_key_revocation: unknown}
Success HTTP status
200

GET /public/releases/{id}

Public

public_id で公開 release evidence を取得します(非公開・非表示は 404)。status は hosted の観測であり、offline の失効証明ではありません。

Request fields
id: release public_id
Response fields / type
public_id, product, version, manifest_base64, manifest_sha256, created_at, bundle: Bundle, current_status
Success HTTP status
200

POST /releases/{id}/status-events

Owner

新しい administrator 署名の withdraw_release 操作で release を取り消せない形で撤回します。release_id は path と一致させます。login の署名では認可できません。

Request fields
release_id: string (matches path), action: withdraw, reason: security_incident | superseded | maintainer_request, authorization: {payload_base64, statement: Envelope}
Response fields / type
event: ReleaseStatusEvent, state: withdrawn
Success HTTP status
201 / 200

POST /release-policies

Owner

immutable な policy version を保存します。"1" から始め 1 ずつ増やします。期待する issuer、issuer・producer key、product、Core protocol は独立して pin してください。API の key directory は信頼の根拠になりません。

Request fields
policy: Policy, authorization: {payload_base64, statement: Envelope}
Response fields / type
id, version: decimal string, policy: Policy, policy_sha256, authorization, created_at
Success HTTP status
201 / 200

GET /release-policies/{id}

Owner

現在の policy version を取得します。owner session、または同じ workspace 内の完全一致 policy label と product に限定された CI credential を受け付けます。古い version を選んで回避することはできません。

Request fields
Request body なし
Response fields / type
Current id, version: decimal string, policy: Policy, policy_sha256, authorization, created_at
Success HTTP status
200

POST /release-policy/evaluations

Owner

現在の policy、release、withdrawal、agent state に対して metadata を評価します。owner session または同じ product と policy に限定された CI credential を受け付けます。allowed_by_policy は実ファイルを検査しません(artifact_bytes_checked は false)。valid_until は目安で最大 30 秒、credential の期限も超えません。同じ実ファイルをローカルで検証して使用してください。

Request fields
release_id: string, policy_id: string, policy_version: decimal string, artifact_name: string, artifact_sha256: string, artifact_size: decimal string
Response fields / type
decision: allowed_by_policy | blocked | unknown, reasons[], release_id, policy_id, policy_version, policy_sha256 (when found), evaluated_at, valid_until, current_status, artifact_name, artifact_sha256, artifact_size, artifact_bytes_checked: false
Success HTTP status
200

POST /release-credentials

Owner

owner session と、{name,product,policy_id,expires_at} に対する Core 0.3 管理者署名の create_release_credential authorization が必要です。その product の policy が事前に存在し、期限は未来かつ最大 90 日である必要があります。201 は token を一度だけ返し、同一の有効な再試行は 200 metadata のみです。応答を失ったら一覧確認・失効後、新しい nonce で再作成します。workspace ごとに active 100 件、保持履歴 1,000 件までです。

Request fields
name: string, product: string, policy_id: string, expires_at: canonical UTC timestamp, authorization: {payload_base64, statement: Envelope}
Response fields / type
credential: {id, name, product, policy_id, created_at, expires_at, revoked_at (optional)}, token: string (201 only; absent on 200 retry)
Success HTTP status
201 / 200

GET /release-credentials

Owner

owner session のみで、CI token は拒否します。期限切れ・失効済みを含む credential metadata を取得します。生の token や hash は返さず、失った token は復元できません。

Request fields
Request body なし
Response fields / type
credentials[] {id, name, product, policy_id, created_at, expires_at, revoked_at (optional)}
Success HTTP status
200

POST /release-credentials/{id}/revoke

Owner

owner session のみで、credential を冪等に失効します。権限を減らすだけなので追加の署名操作は不要です。新規リクエストは拒否されますが、処理中のものは完了する場合があります。offline evidence は変わりません。

Request fields
Request body なし
Response fields / type
credential: {id, name, product, policy_id, created_at, expires_at, revoked_at}
Success HTTP status
200

Retry、limits、expiry

Agent registration:同じ workspace、agent ID、delegation なら 200 と元の record を返し、競合する delegation は 409 agent_already_registered です。有効な authorization は引き続き必要です。

Submission:grant の nonce と body で retry を識別し、同じ nonce で内容が異なると 409 idempotency_conflict です。timeout の後は、retry の前に /me を確認してください。

ERC-8004:同じ nonce と完全に同一の request には元の snapshot(200)を返し、内容が異なると 409 binding_nonce_conflict です。新しい観測には新しい署名付き request が必要です。

  • POST/PUT の body:厳格な UTF-8 JSON、Content-Type: application/json、256 KiB 以下。重複 key、未知のフィールド、JSON number は拒否され、署名対象の数量は十進文字列です。multipart はありません。
  • max_agents と max_daily_certificates は /status にあります(alpha の既定は 100)。certificate は最長 24 時間、delegation は最長 1 年有効です。quota は UTC の日付境界でリセットされます。
  • Login challenge:client IP ごとに毎分 10 件、key ごとに未使用 5 件まで。ERC-8004 creation は IP bucket を共有し、さらに workspace ごとに UTC day 当たり new binding 100 件までです。429 では Retry-After に従います。
  • reference SDK と console は deadline 10 秒、response 上限 8 MiB で、write を自動 retry しません。

code に基づいてエラーを処理する

handler の error は下記の形です。gateway の error は異なることがあるため、HTTP status と Retry-After を確認してください。失敗の response でも、commit されていないとは限りません。

{"error":true,"code":"authentication_required","message":"authentication required"}

HTTP 400

invalid_request, invalid_public_key, invalid_profile, invalid_agent, invalid_submission, submission_too_large, invalid_owner_signature, invalid_source_statement, delegation_exceeds_one_year, invalid_binding_request, binding_request_expired, erc8004_registry_unsupported, unsupported_protocol_version, unsupported_key_algorithm, invalid_release, invalid_release_manifest, release_certificate_mismatch, invalid_release_status_event, invalid_release_policy, invalid_release_evaluation, invalid_release_credential

不正な JSON、無効なフィールドや署名、受け付けられない binding request です。unsupported_protocol_version:未知・非対応の Core バージョン、workspace と異なるバージョン、Core 0.2。unsupported_key_algorithm:Core 0.3 が無効な状態での ML-DSA-65 key。

HTTP 401

authentication_required, invalid_session, invalid_authentication_proof, invalid_ci_credential

session がない・期限切れ、login proof が無効、challenge の再利用、または CI bearer が無効・期限切れ・失効済みです。許可されない owner route は CI token を invalid_session で拒否し、scoped routes は invalid_ci_credential を使用します。

HTTP 403

invalid_agent_authorization, invalid_publication_grant, source_authorization_inactive, invalid_owner_signature, agent_inactive, invalid_release_authorization, release_publication_denied

administrator、agent、EOA owner の proof がこの操作を認可していないか、release が公開されていません。

HTTP 404

agent_not_found, certificate_not_found, profile_not_found, binding_not_found, release_not_found, release_policy_not_found, release_credential_not_found

アクセスできる agent、certificate、binding、release、policy、credential、公開 profile がありません。CI scope 外の release/policy も not found です。

HTTP 409

agent_already_registered, agent_limit_reached, idempotency_conflict, binding_nonce_conflict, erc8004_owner_mismatch, agent_inactive, release_nonce_conflict, policy_version_conflict, release_already_withdrawn, release_conflict, release_credential_nonce_conflict, release_credential_conflict

Registration や nonce の競合、agent quota、inactive な binding agent、owner mismatch、release の重複、policy version の競合、撤回済み release です。競合は上書きの許可になりません。

HTTP 410

core_0_1_retired

Core 0.1 の発行は終了しています。core_0_1_retired:agent の登録、certificate の発行、ERC-8004 binding 0.1、Core 0.1 certificate の register_release、新しい Core 0.1 workspace の作成(login 署名の検証後にのみ拒否)。既存の Core 0.1 workspace では、ログイン、参照、profile 編集、失効、release policy の管理を引き続き行えます。 CI credential の作成も Core 0.3 が必要で、Core 0.1 workspace は core_0_1_retired です。

HTTP 422

erc8004_eoa_only

ERC-8004 owner が contract wallet です。この alpha がサポートするのは EOA ownership consent のみです。

HTTP 429

challenge_rate_limit, daily_submission_limit, daily_binding_limit, release_write_limit, release_rate_limit, release_credential_limit

IP、日次、または credential quota に達しました。Retry-After があれば従い、credential は active 100 件/履歴 1,000 件の上限を確認して、同じリクエストを繰り返さないでください。

HTTP 500

session_unavailable, stored_agent_invalid, binding_unavailable

操作に失敗しました。write を retry する前に認証済みの履歴を確認してください。

HTTP 503

apostille_service_unavailable, challenge_unavailable, workspace_unavailable, agent_unavailable, agent_registration_unavailable, revocation_unavailable, issuance_unavailable, binding_unavailable, erc8004_unavailable, challenge_rate_limit_unavailable, core_0_3_unavailable, release_service_unavailable, release_rate_limit_unavailable, release_credential_unavailable

Hosted issuance、release/credential storage、ERC-8004 reader、rate-limit backend のいずれかが利用できません。core_0_3_unavailable は Core 0.3 の発行が利用できないことを示します。bounded backoff で retry してください。

Privacy と verification の境界

原本、秘密鍵、ZK witness は自分の環境に残ります。release 登録で送るのは canonical manifest と承認だけで、評価に送るのは digest と size です。hash と key は関連付け可能なままです。

certificate が示すのは、範囲内の署名と byte 結合の確認だけです。内容の真実性、法的 identity、現在の authorization や失効状況は証明しません。

ZK budget は実験的で、ローカルの Go SDK/CLI でのみ動作します。hosted の ZK endpoint はありません。単独運用者の development setup では proof を偽造できる可能性があります。

このページは request を送信せず、secret も受け取りません。

Public MCP は独立したインターフェース

匿名 Streamable HTTP で、読み取り専用、鍵は扱いません。bundle/binding の verification と public issuer data 用の tool が 7 つあります。verification は hosted server で実行され、client 側で独立して行うものではありません。

https://iff-mcp-api-production.up.railway.app/mcp/apostille

bundle または detached binding の JSON と、この request 用に選んだ完全一致の issuer/key pin を送ります。trust policy は保持されません。private key や原本は送らず、独立性が必要ならローカルで検証します。

上限:1 request につき JSON-RPC object 1 つ、request 1 MiB・response 10 MiB、毎分 IP ごとに 60・instance ごとに 300 request、同時 4 operation、deadline 20 秒。SSE なしの stateless JSON です。

MCP capabilities

Implementation references