{"openapi":"3.1.0","info":{"title":"API 开放平台 · 客户接口","version":"0.4.0","description":"测试环境（沙箱）：发票接口连接平台内置的企享云模拟器，结果为合成数据，额度单位为测试单位 TEST_UNIT，不产生费用。"},"servers":[{"url":"https://openapi.ulipov.cn","description":"测试环境（沙箱）"}],"paths":{"/v1/mock/echo":{"post":{"operationId":"POST__v1_mock_echo","security":[{"ApiKey":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"scenario":{"type":"string","enum":["success","business_failure","pending","unknown","exception"]}},"required":["scenario"]}}}},"responses":{"200":{"description":"Mock outcome SUCCESS or BUSINESS_FAILURE"},"202":{"description":"Non-final mock outcome PENDING or UNKNOWN"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Mock provider or local dependency unavailable"}},"summary":"连通性测试","description":"不计量的模拟调用，用于验证 Key 是否可用。","tags":["基础与测试"]}},"/v1/mock/metered-writes":{"post":{"operationId":"POST__v1_mock_metered_writes","security":[{"ApiKey":[]}],"parameters":[{"in":"header","name":"idempotency-key","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"scenario":{"type":"string","enum":["success","business_failure","pending","unknown","unknown_failure","unavailable"]},"timing":{"type":"string","enum":["quick","slow"]}},"required":["scenario"]}}}},"responses":{"200":{"description":"Previously admitted operation with a confirmed terminal result"},"202":{"description":"Admitted or replayed operation without a terminal result"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"413":{"description":"Mock body exceeds 256 bytes"},"429":{"description":"Quota exhausted, business slots full, or rate limited","headers":{"Retry-After":{"description":"Seconds to wait when rate limited or slots are full","schema":{"type":"integer"}}}},"503":{"description":"Circuit or database unavailable. If outcome is unknown, repeat only with the original key and body."}},"summary":"计量写入（模拟）","description":"单笔计量的模拟写操作。","tags":["基础与测试"]}},"/v1/requests/{requestId}":{"get":{"operationId":"GET__v1_requests_requestId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"requestId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询请求","description":"只读本地结果。","tags":["基础与测试"]}},"/v1/tasks/{taskId}":{"get":{"operationId":"GET__v1_tasks_taskId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"taskId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询任务","description":"只读本地结果。","tags":["基础与测试"]}},"/v1/mock/metered-batches":{"post":{"operationId":"POST__v1_mock_metered_batches","security":[{"ApiKey":[]}],"parameters":[{"in":"header","name":"idempotency-key","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"integer","minimum":1,"maximum":999999},"profile":{"type":"string","enum":["small","large"]},"scenario":{"type":"string","enum":["success","business_failure","pending","unknown","unknown_failure","overrun","missing_units"]},"timing":{"type":"string","enum":["quick","slow"]}},"required":["itemId","profile","scenario"]}}},"required":["items"]}}}},"responses":{"200":{"description":"Terminal replay with per-item accounting"},"202":{"description":"Atomic batch admitted or replayed while items remain unresolved"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"413":{"description":"Mock batch body exceeds 4096 bytes"},"429":{"description":"Quota, business slots or rate admission rejected the entire batch","headers":{"Retry-After":{"description":"Seconds to wait for a rate or business-slot gate","schema":{"type":"integer"}}}},"503":{"description":"Local dependency unavailable. Replay uncertain admission with the original key and body."}},"summary":"计量批量（模拟）","description":"批量计量的模拟写操作。","tags":["基础与测试"]}},"/v1/mock/metered-batches/{batchId}":{"get":{"operationId":"GET__v1_mock_metered_batches_batchId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"batchId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询计量批次","description":"只读本地结果。","tags":["基础与测试"]}},"/v1/mock/qxy/verifications":{"post":{"operationId":"POST__v1_mock_qxy_verifications","security":[{"ApiKey":[]}],"parameters":[{"in":"header","name":"idempotency-key","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"integer","minimum":1,"maximum":999999},"invoiceNumber":{"type":"string","pattern":"^9999[0-9]{16}$"},"issueDate":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"totalCents":{"type":"integer","minimum":1,"maximum":100000000}},"required":["itemId","invoiceNumber","issueDate","totalCents"]}}},"required":["items"]}}}},"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"202":{"description":"Durable synthetic admission pending or unknown"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"413":{"description":"Synthetic batch exceeds 4096 bytes"},"415":{"description":"Unsupported request media type"},"429":{"description":"Quota, business slot or rate gate denied admission"},"503":{"description":"Local dependency unavailable. Retry with the original key and body."}},"summary":"发票查验（批量）","description":"1–10 张发票整批受理，每张独立查验、独立计量。返回 202 后用 GET 轮询批次结果。","tags":["发票服务"]}},"/v1/mock/qxy/verifications/{batchId}":{"get":{"operationId":"GET__v1_mock_qxy_verifications_batchId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"batchId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询查验批次","description":"只读本地结果，不消耗额度，可放心轮询。","tags":["发票服务"]}},"/v1/mock/qxy/format-tasks":{"post":{"operationId":"POST__v1_mock_qxy_format_tasks","security":[{"ApiKey":[]}],"parameters":[{"in":"header","name":"idempotency-key","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"items":{"type":"array","minItems":1,"maxItems":10,"items":{"type":"object","additionalProperties":false,"properties":{"itemId":{"type":"integer","minimum":1,"maximum":999999},"invoiceNumber":{"type":"string","pattern":"^9999[0-9]{16}$"},"issueDate":{"type":"string","pattern":"^[0-9]{4}-[0-9]{2}-[0-9]{2}$"},"totalCents":{"type":"integer","minimum":1,"maximum":100000000}},"required":["itemId","invoiceNumber","issueDate","totalCents"]}}},"required":["items"]}}}},"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"202":{"description":"Durable synthetic admission pending or unknown"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"413":{"description":"Synthetic batch exceeds 4096 bytes"},"415":{"description":"Unsupported request media type"},"429":{"description":"Quota, business slot or rate gate denied admission"},"503":{"description":"Local dependency unavailable. Retry with the original key and body."}},"summary":"版式文件任务提交（批量）","description":"受理后每张发票生成一个任务（taskId = 子项 requestId），状态 PENDING，额度保持预占直到最终结果。","tags":["发票服务"]}},"/v1/mock/qxy/format-tasks/{batchId}":{"get":{"operationId":"GET__v1_mock_qxy_format_tasks_batchId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"batchId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"P1 local response; no real upstream dispatch"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询版式提交批次","description":"只读本地结果。","tags":["发票服务"]}},"/v1/mock/qxy/tasks/{taskId}":{"get":{"operationId":"GET__v1_mock_qxy_tasks_taskId","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"taskId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Local cached task and extraction budget"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"查询版式任务","description":"只读本地缓存，返回状态、剩余提取次数和文件链接（完成后）。","tags":["发票服务"]}},"/v1/mock/qxy/tasks/{taskId}/result-fetch":{"post":{"operationId":"POST__v1_mock_qxy_tasks_taskId_result_fetch","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"taskId","required":true,"schema":{"type":"string","format":"uuid"}},{"in":"header","name":"idempotency-key","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9._~-]{1,128}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{},"required":[]}}}},"responses":{"200":{"description":"Prior extraction permit replay; see task for local status"},"202":{"description":"Extraction permit queued or active"},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Extraction unavailable, active under a different key, or budget exhausted"},"413":{"description":"Body too large"},"415":{"description":"Unsupported request media type"},"429":{"description":"Authentication rate limit"},"503":{"description":"Local dependency unavailable. Retry with the original key."}},"summary":"提取版式结果","description":"明确的消费动作，每个任务最多 3 次；同一 Idempotency-Key 重放返回原许可。","tags":["发票服务"]}},"/v1/mock/qxy/tasks/{taskId}/file":{"get":{"operationId":"GET__v1_mock_qxy_tasks_taskId_file","security":[{"ApiKey":[]}],"parameters":[{"in":"path","name":"taskId","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Bounded local synthetic attachment","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"400":{"description":"Invalid request"},"401":{"description":"Invalid identity"},"403":{"description":"Forbidden/CSRF/scope"},"404":{"description":"Absent or invisible"},"409":{"description":"Conflict"},"429":{"description":"Authentication rate limit"},"503":{"description":"Dependency unavailable; no dispatch"}},"summary":"下载版式文件","description":"任务完成后可下载；需要当前应用的有效 Key。","tags":["发票服务"]}}},"x-qxy-enabled":true,"x-error-codes":[{"status":400,"code":"INVALID_REQUEST","meaning":"请求格式、字段类型或必填项不符合接口定义；415 媒体类型错误也返回此码。"},{"status":400,"code":"DUPLICATE_JSON_KEY","meaning":"同一 JSON 对象内出现重复字段。"},{"status":400,"code":"INVALID_BATCH_SIZE","meaning":"批量条数不在 1–10 之间。"},{"status":400,"code":"DUPLICATE_BATCH_ITEM","meaning":"批量内 itemId 重复。"},{"status":400,"code":"DUPLICATE_MOCK_INVOICE","meaning":"批量内发票号码重复。"},{"status":400,"code":"INVALID_ISSUE_DATE","meaning":"开票日期不是有效的 yyyy-MM-dd 日期。"},{"status":401,"code":"INVALID_API_KEY","meaning":"API Key 缺失、格式错误、已过期、已停用或已吊销，或所属应用/租户不可用。"},{"status":403,"code":"SCOPE_DENIED","meaning":"Key 或应用未包含该接口 scope，或租户未获该接口授权。"},{"status":403,"code":"TEST_POLICY_REQUIRED","meaning":"租户尚未配置计量策略，请联系平台开通。"},{"status":404,"code":"NOT_FOUND","meaning":"资源不存在，或不属于当前应用（不区分两者）。"},{"status":409,"code":"IDEMPOTENCY_CONFLICT","meaning":"同一 Idempotency-Key 已用于不同的请求体。"},{"status":409,"code":"FETCH_NOT_AVAILABLE","meaning":"任务当前不处于可提取结果的状态。"},{"status":409,"code":"FETCH_IN_PROGRESS","meaning":"该任务已有一笔提取在处理中。"},{"status":409,"code":"FETCH_BUDGET_EXHAUSTED","meaning":"该任务的结果提取次数（3 次）已用完。"},{"status":413,"code":"MOCK_BODY_TOO_LARGE","meaning":"请求体超过接口上限。"},{"status":429,"code":"QUOTA_EXHAUSTED","meaning":"额度不足；整批不受理、不扣减。"},{"status":429,"code":"RATE_LIMITED","meaning":"超过速率限制，按 Retry-After 秒后重试。"},{"status":429,"code":"BUSINESS_CONCURRENCY_LIMIT","meaning":"在途业务数已满，按 Retry-After 秒后重试。"},{"status":503,"code":"UPSTREAM_CREDENTIAL_UNAVAILABLE","meaning":"平台为你配置的上游通道暂不可用，请求未受理、未扣额度。"},{"status":503,"code":"MOCK_CIRCUIT_OPEN","meaning":"上游通道熔断中，请求未受理。"},{"status":503,"code":"DEPENDENCY_UNAVAILABLE","meaning":"平台依赖暂不可用。写操作若 outcome=UNKNOWN，只能用原 Idempotency-Key 和原请求体重试。"}],"components":{"securitySchemes":{"ApiKey":{"type":"http","scheme":"bearer","description":"在客户控制台创建的 API Key，形如 ak_test_<id>.<secret>，仅创建时显示一次。"}}}}