Hosted REST API · alpha

构建 Apostille 集成。

注册 agent、提交已明确授权的 statement,并获取可移植 certificate。原始文件和私钥保留在你的应用程序中。

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

从 public request 开始

status endpoint 不需要 token。签发前请先检查 enabled,并从 limits 读取 workspace 限额。

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,之后登录会回到该 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。响应含 challenge_id、issuer、message 与 expires_at(五分钟)。
  2. 以设置的 issuer、key 的 fingerprint、返回的 UUID v4 challenge_id 与 canonical UTC expires_at,重建下方 message(结尾不含换行)。只接受七分钟内到期的 challenge。
  3. 在本地签名完全相同的 UTF-8 message(Core 0.1 用 Ed25519,Core 0.3 用 ML-DSA-65)。将 challenge_id、message 与 unpadded-base64url signature POST 至 /auth/verify。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 signature。

CI 只读凭证

API 预览,是否可用依各部署而定。使用前请确认目标服务 /status 的 enabled: true、features 同时包含 supply_chain_releases 和 supply_chain_ci_credentials,并确认实际端点可用。

不透明的 CI bearer 固定绑定单一工作区、完全匹配的 product 和 policy label,只能读取范围内 release、当前策略及评估元数据;其他 owner routes 一律拒绝。仍须指定最新 policy version,并独立选择 issuer/producer pins。

通过 Core 0.3 管理员 session 加上已签名的 create_release_credential 操作创建。到期时间必须明确指定,最多 90 天(建议 30 天);范围不可更改,也没有通配符。token 只返回一次,重试只返回 metadata。管理员 session 可列出或撤销凭证。每次请求都检查到期与撤销,但已进行中的请求可能完成。

Core 版本与 hosted Core 0.3

Hosted service 只签发 Core 0.3(ML-DSA-65),并在 GET /status 的 protocols 中列出。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 使用第一行为 iff-apostille/login/0.3 的 login message(见下方);以 pure ML-DSA-65 与空 context 签名(签名 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 登录。
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

只有第一行不同。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 的 protocol,返回 bundle 的 protocol 等于所提交的 protocol。新的 certificate 请 pin Core 0.3 issuer key,过去的请 pin Core 0.1 key。

分别授权每一次 publication

登录并不授权 publication。请用 Core SDK 或 CLI 创建 signed envelope,不要自创 serialization。

  1. administrator 签名 delegation,agent 签名 acceptance,绑定相同的 agent 与 service audience。以 POST /agents 注册。
  2. 在本地对原始文件做 hash,并创建 agent 签名的 origin-statement。原始文件由你的应用程序选择并保留。
  3. administrator 签名另一份 publication grant,绑定 statement digest、audience、nonce 与 private/public visibility。只将 statement 与 grant POST 至 /submissions。login token 不能取代 grant。
  4. visibility 由 signed grant 决定。public grant 授权分发整份 signed bundle(可链接的 key、identifier、timestamp、digest、size),不含 workspace profile。
  5. 下载 bundle,以独立选定的 issuer/key pin 在本地验证。API 返回的 key 不会自动成为 trusted key。

Endpoint 参考

路径均相对于 REST base URL;GET 也支持 HEAD。Owner routes 使用管理员 session,只有下列三个读取/评估端点也接受 scoped CI。Public routes 不需要 token;公开 release 使用 public_id。

字段清单描述响应形状,不是可直接发送的 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 会使最旧的失效。

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 name 与 public-profile visibility。不会公开任何 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 的新签发权限。既有 signed bytes 不变;offline verification 看不到撤销。

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

直接下载 signed Bundle。其他 workspace 无法获取。

Request fields
无 request body
Response fields / type
Bundle
Success HTTP status
200

POST /certificates/{id}/hide

Owner

停止公开提供证书及依赖它的 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 读取明确设为 public 的 certificate(private 或 hidden 返回 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 读取明确设为 public 的 workspace profile。标记 self_declared,不含 key 与 private fields。

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 是否启用、支持的 registries,以及签发的 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 signature。返回 private、immutable 的 issuer_checked snapshot;不发送 chain transaction。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 观察到的 ownership,不证明 current 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。登记已由证书涵盖的 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,或同工作区、完全匹配 product 的 CI 凭证。有效签名不代表当前允许部署。

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 observation,不是离线撤销证明。

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 必须与路径相同。登录签名不能代替授权。

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

保存不可变的 policy version,从 "1" 开始逐次加一。Expected issuer、issuer 与 producer keys、product 及 Core protocols 都须独立 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,或同工作区、完全匹配 policy label 与 product 的 CI 凭证;不能选择旧版本绕过策略。

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 评估元数据。接受 owner session,或绑定同 product/policy 的 CI 凭证。allowed_by_policy 不检查实际字节(artifact_bytes_checked 为 false);valid_until 仅供参考,最多 30 秒且不晚于凭证到期。请在本地验证并使用同一份实际文件。

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 和 Core 0.3 管理员对 {name,product,policy_id,expires_at} 签名的 create_release_credential 授权。相同 product 的策略须已存在,到期时间须在未来且最多 90 天。201 只返回一次 token;完全相同且授权仍有效的重试返回 200 metadata。丢失响应时先列出/撤销,再以新 nonce 创建替代凭证。每工作区最多 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。列出凭证 metadata,含过期/撤销记录。不返回原始 token 或哈希,也无法恢复丢失的 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,以幂等操作撤销凭证。此操作只缩减权限,不需要额外签名授权。后续请求会失败,但已进行中的请求可能完成;离线证据不变。

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。新的 observation 需要新的 signed request。

  • POST/PUT body:严格 UTF-8 JSON,Content-Type: application/json,不超过 256 KiB。duplicate key、unknown field 与 JSON number 会被拒绝;signed 数量使用 decimal string。不支持 multipart。
  • max_agents 与 max_daily_certificates 来自 /status(alpha 默认为 100)。Certificate 最长有效 24 小时,delegation 最长一年。quota 在 UTC day boundary 重设。
  • Login challenge:每个 client IP 每分钟 10 次,每个 key 最多五个未使用。ERC-8004 creation 共用 IP bucket,另限每个 workspace 每个 UTC day 100 个 new binding。收到 429 请遵守 Retry-After。
  • Reference SDK 与 console 使用 10 秒 deadline 与 8 MiB response 上限,不会自动 retry write。

按 code 处理失败

Handler error 使用如下 shape;gateway error 可能不同,请检查 HTTP status 与 Retry-After。失败响应不代表没有 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

Malformed JSON、invalid field 或 signature,或无法接受的 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 缺失或过期、登录证明无效、challenge 重放,或 CI bearer 无效/过期/已撤销。不允许的 owner route 以 invalid_session 拒绝 CI token;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 的证明未授权此操作,或 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、证书、binding、release、policy、credential 或公开 profile;CI 范围外的 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 凭证创建也须使用 Core 0.3;Core 0.1 工作区返回 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、每日或凭证配额。有 Retry-After 时请遵守;凭证须先核对 100 个有效/1,000 条历史上限,勿原样重试。

HTTP 500

session_unavailable, stored_agent_invalid, binding_unavailable

操作失败。重试写入前请先查看登录后的历史记录。

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 boundaries

原件、私钥与 ZK witness 留在自己的环境。Release 登记只上传 canonical manifest 与授权;evaluation 只收 digest 与 size。Hash 与 key 仍可关联。

Certificate 只在其范围内证明 signature 与 byte-binding check,不证明 content truth、legal identity、current authorization 或撤销状态。

ZK budget 为实验性功能,只在本地 Go SDK/CLI 运行,没有 hosted ZK endpoint。单方 development setup 可能伪造 proof。

此页面不会发送 request,也不接收 secret。

Public MCP 是独立接口

匿名 Streamable HTTP,只读,不处理密钥。七个 tool 用于 bundle/binding verification 与 public issuer data。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 或原件。需要独立查验时请在本地验证。

限制:每个 request 一个 JSON-RPC object,request 1 MiB、response 10 MiB,每分钟每个 IP 60 次、每个 instance 300 次,最多四个 concurrent operation,deadline 20 秒。返回 stateless JSON,不使用 SSE。

MCP capabilities

Implementation references