openapi: 3.1.0 info: title: 黑料大事记 Public API version: 2.0.0 summary: Create and manage translation projects from your applications. description: >- Use a 黑料大事记 API key to upload files or send JSON/text, create translation projects, monitor progress, retrieve completed translations, optionally request quotes, and receive webhook updates. Every response includes 黑料大事记-Request-Id and 黑料大事记-API-Version. Authenticated responses also include RateLimit-Policy and RateLimit; replayed requests include Idempotency-Replayed: true. servers: - url: https://apis.stepes.com/v2 description: Production x-stepes-response-header-policy: all_responses: 黑料大事记-Request-Id: {$ref: '#/components/headers/黑料大事记RequestId'} 黑料大事记-API-Version: {$ref: '#/components/headers/黑料大事记ApiVersion'} authenticated_responses: RateLimit-Policy: {$ref: '#/components/headers/RateLimitPolicy'} RateLimit: {$ref: '#/components/headers/RateLimit'} idempotency_replays: Idempotency-Replayed: {$ref: '#/components/headers/IdempotencyReplayed'} tags: - name: System description: Public API identity and release discovery. - name: Account description: Account details, API key permissions, limits, and capabilities. - name: Discovery description: Available languages, services, and turnaround options. - name: Files description: Private source uploads, metadata, and retained inline content. - name: Projects description: Create and track translation projects and retrieve completed translations. - name: Quotes description: Review pricing before creating a translation project. - name: Webhooks description: Signed endpoint registration, rotation, delivery history, and retry. paths: /: get: tags: [System] operationId: getApiInfo summary: Get API identity and version description: Confirm the public API base URL, semantic version, and direct API-key authentication mode. security: [] responses: '200': description: API information content: application/json: schema: $ref: '#/components/schemas/ApiInfo' /account: get: tags: [Account] operationId: getAccount summary: Get account details description: Return the account profile, currency, API key environment, permissions, and whether project creation is enabled. x-stepes-required-scopes: [account:read] responses: '200': description: Account and API access details content: application/json: schema: {$ref: '#/components/schemas/Account'} '401': {$ref: '#/components/responses/Unauthorized'} '403': {$ref: '#/components/responses/Forbidden'} /capabilities: get: tags: [Account] operationId: getCapabilities summary: Get key scopes, limits, and enabled capabilities description: Discover effective key scopes, project and quote availability, webhook events, request limits, content limits, and idempotency policy. x-stepes-required-scopes: [account:read] responses: '200': description: Capabilities content: application/json: schema: {$ref: '#/components/schemas/Capabilities'} '401': {$ref: '#/components/responses/Unauthorized'} /languages: get: tags: [Discovery] operationId: listLanguages summary: List active source and target languages description: List source and target languages available to your account, optionally filtered by search text. x-stepes-required-scopes: [languages:read] parameters: - name: search in: query schema: {type: string, maxLength: 100} - name: limit in: query schema: {type: integer, minimum: 1, maximum: 200, default: 100} responses: '200': description: Language list content: application/json: schema: type: object required: [object, data] properties: object: {const: list} data: type: array items: {$ref: '#/components/schemas/Language'} '401': {$ref: '#/components/responses/Unauthorized'} /service-options: get: tags: [Discovery] operationId: listServiceOptions summary: List supported project services and turnaround options description: List the service codes and turnaround values accepted when creating projects or quotes. x-stepes-required-scopes: [account:read] responses: '200': description: Service options content: application/json: schema: type: object required: [object, data, has_more, next_cursor] properties: object: {const: list} data: type: array items: {$ref: '#/components/schemas/ServiceOption'} has_more: {const: false} next_cursor: {type: 'null'} '401': {$ref: '#/components/responses/Unauthorized'} /files: post: tags: [Files] operationId: uploadFile summary: Upload a source file description: Upload one source file and receive a file ID that can be used to create a project or quote. x-stepes-required-scopes: [files:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: multipart/form-data: schema: type: object required: [file] properties: file: {type: string, format: binary, description: One private source file within the current max_file_bytes capability limit.} responses: '201': description: File created headers: Location: {$ref: '#/components/headers/Location'} content: application/json: schema: {$ref: '#/components/schemas/File'} '401': {$ref: '#/components/responses/Unauthorized'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /files/{fileId}: parameters: - $ref: '#/components/parameters/FileId' get: tags: [Files] operationId: getFile summary: Get source file metadata and analysis state description: Return file metadata and whether the uploaded source is ready to use. x-stepes-required-scopes: [files:read] responses: '200': description: File content: application/json: schema: {$ref: '#/components/schemas/File'} '404': {$ref: '#/components/responses/NotFound'} delete: tags: [Files] operationId: deleteFile summary: Delete an unused source file description: Delete an uploaded source file before it has been attached to a quote or project. x-stepes-required-scopes: [files:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' responses: '204': {description: File deleted} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /files/{fileId}/download: get: tags: [Files] operationId: downloadSourceFile summary: Download a source file description: Download the original bytes of a source file available to your API key. x-stepes-required-scopes: [files:read] parameters: - $ref: '#/components/parameters/FileId' responses: '200': description: Source file bytes content: application/octet-stream: schema: {type: string, format: binary} '404': {$ref: '#/components/responses/NotFound'} '422': {$ref: '#/components/responses/ValidationError'} /files/{fileId}/content: get: tags: [Files] operationId: getSourceContent summary: Retrieve exact inline JSON or text source content description: Return the exact retained JSON structure or text submitted through an inline project or quote request. x-stepes-required-scopes: [files:read] parameters: - $ref: '#/components/parameters/FileId' responses: '200': description: Structured source content content: application/json: schema: {$ref: '#/components/schemas/StructuredContent'} '404': {$ref: '#/components/responses/NotFound'} '422': {$ref: '#/components/responses/ValidationError'} /projects: post: tags: [Projects] operationId: createProject summary: Create a translation project description: >- Start a translation project from uploaded files or inline JSON/text. Provide source and target languages and optional project or billing references. The response includes a project ID that can be used to track progress and retrieve completed translations. x-stepes-required-scopes: [projects:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/ProjectInput'} responses: '201': description: Translation project created headers: Location: {$ref: '#/components/headers/Location'} content: application/json: schema: {$ref: '#/components/schemas/Project'} '401': {$ref: '#/components/responses/Unauthorized'} '403': {$ref: '#/components/responses/Forbidden'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} get: tags: [Projects] operationId: listProjects summary: List translation projects description: List projects created with your API key, using cursor pagination and the documented filters. x-stepes-required-scopes: [projects:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/Status' - $ref: '#/components/parameters/ExternalId' - $ref: '#/components/parameters/CreatedAfter' - $ref: '#/components/parameters/CreatedBefore' responses: '200': description: Project page content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorPage' - type: object properties: data: type: array items: {$ref: '#/components/schemas/Project'} '422': {$ref: '#/components/responses/ValidationError'} /projects/{projectId}: get: tags: [Projects] operationId: getProject summary: Get project status and details description: Return current status, progress, source files, target-language work, delivery readiness, and billing summary. x-stepes-required-scopes: [projects:read] parameters: - $ref: '#/components/parameters/ProjectId' responses: '200': description: Project content: application/json: schema: {$ref: '#/components/schemas/Project'} '404': {$ref: '#/components/responses/NotFound'} /projects/{projectId}/cancel: post: tags: [Projects] operationId: cancelProject summary: Cancel a translation project description: Request cancellation of an eligible project. Completed work and available deliveries are preserved. x-stepes-required-scopes: [projects:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: type: object required: [reason] properties: reason: {type: string, minLength: 1, maxLength: 2000} reason_code: {type: [string, 'null'], maxLength: 100} responses: '200': description: Cancelled project content: application/json: schema: {$ref: '#/components/schemas/Project'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /projects/{projectId}/deliveries: get: tags: [Projects] operationId: listProjectDeliveries summary: List completed translations description: List translated files or structured JSON/text results currently available for a project. x-stepes-required-scopes: [deliveries:read] parameters: - $ref: '#/components/parameters/ProjectId' responses: '200': description: Delivery list content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorPage' - type: object properties: data: type: array items: {$ref: '#/components/schemas/Delivery'} '404': {$ref: '#/components/responses/NotFound'} /projects/{projectId}/deliveries/{deliveryId}/download: get: tags: [Projects] operationId: downloadDelivery summary: Download a translated file description: Download the completed translated file for a project delivery. x-stepes-required-scopes: [deliveries:read] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DeliveryId' responses: '200': description: Target file bytes content: application/octet-stream: schema: {type: string, format: binary} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} /projects/{projectId}/deliveries/{deliveryId}/content: get: tags: [Projects] operationId: getDeliveryContent summary: Get structure-preserving JSON or text delivery description: Reconstruct translated JSON or text only when completed target segments align exactly with the retained source manifest. x-stepes-required-scopes: [deliveries:read] parameters: - $ref: '#/components/parameters/ProjectId' - $ref: '#/components/parameters/DeliveryId' responses: '200': description: Structured delivery content: application/json: schema: {$ref: '#/components/schemas/StructuredContent'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} /quotes: post: tags: [Quotes] operationId: createQuote summary: Create a quote description: Calculate an editable price estimate from uploaded files or inline JSON/text without starting translation. x-stepes-required-scopes: [quotes:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/ProjectInput'} responses: '201': description: Quote created headers: Location: {$ref: '#/components/headers/Location'} content: application/json: schema: {$ref: '#/components/schemas/Quote'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} get: tags: [Quotes] operationId: listQuotes summary: List quotes description: List quotes created with your API key, using cursor pagination and the documented filters. x-stepes-required-scopes: [quotes:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' - $ref: '#/components/parameters/Status' - $ref: '#/components/parameters/ExternalId' - $ref: '#/components/parameters/CreatedAfter' - $ref: '#/components/parameters/CreatedBefore' responses: '200': description: Quote page content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorPage' - type: object properties: data: type: array items: {$ref: '#/components/schemas/Quote'} '422': {$ref: '#/components/responses/ValidationError'} /quotes/{quoteId}: parameters: - $ref: '#/components/parameters/QuoteId' get: tags: [Quotes] operationId: getQuote summary: Get a quote description: Return current quote inputs, source files, lifecycle state, currency, totals, expiry, and converted project ID when present. x-stepes-required-scopes: [quotes:read] responses: '200': description: Quote content: application/json: schema: {$ref: '#/components/schemas/Quote'} '404': {$ref: '#/components/responses/NotFound'} patch: tags: [Quotes] operationId: updateQuote summary: Recalculate an editable quote with revised inputs description: Update an editable quote and recalculate its price before submission or acceptance. x-stepes-required-scopes: [quotes:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/QuoteUpdate'} responses: '200': description: Revised quote content: application/json: schema: {$ref: '#/components/schemas/Quote'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /quotes/{quoteId}/submit: post: tags: [Quotes] operationId: submitQuote summary: Submit and freeze a quote revision description: Submit the current quote for approval and prevent further draft edits. x-stepes-required-scopes: [quotes:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/QuoteId' - $ref: '#/components/parameters/IdempotencyKey' requestBody: content: application/json: schema: type: object properties: submission_notes: {type: [string, 'null'], maxLength: 5000} responses: '200': description: Submitted quote content: application/json: schema: {$ref: '#/components/schemas/Quote'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /quotes/{quoteId}/accept: post: tags: [Quotes] operationId: acceptQuote summary: Accept a quote and create a project description: Accept an eligible quote and start the translation project. The response contains the newly created project. x-stepes-required-scopes: [quotes:write, projects:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/QuoteId' - $ref: '#/components/parameters/IdempotencyKey' requestBody: content: application/json: schema: {$ref: '#/components/schemas/BillingMetadata'} responses: '201': description: Translation project created headers: Location: {$ref: '#/components/headers/Location'} content: application/json: schema: {$ref: '#/components/schemas/Project'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /webhooks: get: tags: [Webhooks] operationId: listWebhooks summary: List webhook endpoints description: List signed HTTPS webhook endpoints registered for your account and API environment. x-stepes-required-scopes: [webhooks:read] parameters: - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' responses: '200': description: Webhook list content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorPage' - type: object properties: data: type: array items: {$ref: '#/components/schemas/WebhookEndpoint'} post: tags: [Webhooks] operationId: createWebhook summary: Create a signed HTTPS webhook endpoint description: The signing secret is returned only in this response. x-stepes-required-scopes: [webhooks:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/WebhookCreateInput'} responses: '201': description: Webhook created; copy the secret now headers: Location: {$ref: '#/components/headers/Location'} content: application/json: schema: allOf: - $ref: '#/components/schemas/WebhookEndpoint' - type: object required: [secret] properties: secret: {type: string, writeOnly: true} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} /webhooks/{webhookId}: parameters: - $ref: '#/components/parameters/WebhookId' get: tags: [Webhooks] operationId: getWebhook summary: Get a webhook endpoint without its secret description: Return one webhook endpoint and its subscriptions without returning the signing secret. x-stepes-required-scopes: [webhooks:read] responses: '200': description: Webhook content: application/json: schema: {$ref: '#/components/schemas/WebhookEndpoint'} '404': {$ref: '#/components/responses/NotFound'} patch: tags: [Webhooks] operationId: updateWebhook summary: Update URL, events, description, or status description: Update the HTTPS destination, event subscriptions, display name, or active state. x-stepes-required-scopes: [webhooks:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' requestBody: required: true content: application/json: schema: {$ref: '#/components/schemas/WebhookInput'} responses: '200': description: Updated webhook content: application/json: schema: {$ref: '#/components/schemas/WebhookEndpoint'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} '422': {$ref: '#/components/responses/ValidationError'} delete: tags: [Webhooks] operationId: deleteWebhook summary: Revoke a webhook endpoint description: Revoke an endpoint so no additional events are scheduled for delivery to it. x-stepes-required-scopes: [webhooks:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/IdempotencyKey' responses: '204': {description: Webhook revoked} '404': {$ref: '#/components/responses/NotFound'} /webhooks/{webhookId}/rotate-secret: post: tags: [Webhooks] operationId: rotateWebhookSecret summary: Rotate a signing secret and show it once description: Generate a replacement signing secret, return it once, and retain the previous secret only for the configured verification grace period. x-stepes-required-scopes: [webhooks:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/WebhookId' - $ref: '#/components/parameters/IdempotencyKey' responses: '200': description: Replacement secret content: application/json: schema: allOf: - $ref: '#/components/schemas/WebhookEndpoint' - type: object required: [secret] properties: secret: {type: string, writeOnly: true} '404': {$ref: '#/components/responses/NotFound'} /webhook-deliveries: get: tags: [Webhooks] operationId: listWebhookDeliveries summary: List webhook delivery history description: List delivery status and attempt timing for your webhook endpoints. x-stepes-required-scopes: [webhooks:read] parameters: - name: limit in: query schema: {type: integer, minimum: 1, maximum: 100, default: 25} - $ref: '#/components/parameters/Cursor' - name: status in: query schema: {type: string} responses: '200': description: Delivery history content: application/json: schema: allOf: - $ref: '#/components/schemas/CursorPage' - type: object properties: data: type: array items: {$ref: '#/components/schemas/WebhookDelivery'} /webhook-deliveries/{deliveryId}/retry: post: tags: [Webhooks] operationId: retryWebhookDelivery summary: Redeliver the original persisted event description: Queue another attempt for the same persisted event and endpoint without creating a duplicate event record. x-stepes-required-scopes: [webhooks:write] x-stepes-idempotent: true parameters: - $ref: '#/components/parameters/WebhookDeliveryId' - $ref: '#/components/parameters/IdempotencyKey' responses: '202': description: Redelivery queued content: application/json: schema: {$ref: '#/components/schemas/WebhookDelivery'} '404': {$ref: '#/components/responses/NotFound'} '409': {$ref: '#/components/responses/Conflict'} components: securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: 黑料大事记 API key description: Opaque stp_live_* or stp_test_* key issued in the 黑料大事记 client portal. parameters: IdempotencyKey: name: Idempotency-Key in: header required: true description: Unique operation key. Reuse it only with the same method, path, and request body. schema: {type: string, minLength: 8, maxLength: 255} Limit: name: limit in: query schema: {type: integer, minimum: 1, maximum: 100, default: 25} Cursor: name: cursor in: query description: Opaque signed cursor from next_cursor. schema: {type: string} Status: name: status in: query schema: {type: string} ExternalId: name: external_id in: query schema: {type: string, maxLength: 255} CreatedAfter: name: created_after in: query schema: {type: string, format: date-time} CreatedBefore: name: created_before in: query schema: {type: string, format: date-time} FileId: name: fileId in: path required: true schema: {type: string, pattern: '^file_[A-Za-z0-9_-]{10,64}$'} ProjectId: name: projectId in: path required: true schema: {type: string, pattern: '^proj_[A-Za-z0-9_-]{10,64}$'} QuoteId: name: quoteId in: path required: true schema: {type: string, pattern: '^quote_[A-Za-z0-9_-]{10,64}$'} DeliveryId: name: deliveryId in: path required: true schema: {type: string, pattern: '^delivery_[A-Za-z0-9_-]{10,64}$'} WebhookId: name: webhookId in: path required: true schema: {type: string, pattern: '^wh_[A-Za-z0-9_-]{10,64}$'} WebhookDeliveryId: name: deliveryId in: path required: true schema: {type: string, pattern: '^whd_[A-Za-z0-9_-]{10,64}$'} headers: Location: description: Canonical URL of the created resource. schema: {type: string, format: uri} 黑料大事记RequestId: description: Server-generated request identifier for support and audit correlation. schema: {type: string, format: uuid} 黑料大事记ApiVersion: description: Effective 黑料大事记 API semantic version. schema: {type: string, example: 2.0.0} RateLimitPolicy: description: Effective request limit and window for the authenticated key. schema: {type: string, example: '120;w=60'} RateLimit: description: Current limit, remaining requests, and reset interval. schema: {type: string, example: 'limit=120, remaining=119, reset=60'} IdempotencyReplayed: description: Present with value true when a stored mutation response is replayed. schema: {type: string, enum: ['true']} responses: BadRequest: description: Invalid cursor or malformed request content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} Unauthorized: description: Missing, malformed, expired, revoked, or disallowed API key content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} Forbidden: description: Missing API key permission or account access content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} NotFound: description: Resource was not found or is not available to this API key content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} Conflict: description: Idempotency conflict or invalid lifecycle transition content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} ValidationError: description: Request validation failed content: application/problem+json: schema: {$ref: '#/components/schemas/Problem'} schemas: ApiInfo: type: object required: [object, name, version, base_url, authentication] properties: object: {const: api} name: {const: 黑料大事记 Public API} version: {type: string} base_url: {const: 'https://apis.stepes.com/v2'} authentication: {const: bearer_api_key} Account: type: object additionalProperties: false required: [object, id, name, environment, currency, invoice_terms, project_submission_enabled, scopes] properties: object: {const: account} id: {type: string, pattern: '^pac_[A-Za-z0-9_-]{10,64}$'} name: {type: string} environment: {type: string, enum: [live, test]} currency: {type: string, minLength: 3, maxLength: 3, examples: [USD]} invoice_terms: {type: boolean} project_submission_enabled: {type: boolean} scopes: type: array uniqueItems: true items: {$ref: '#/components/schemas/ApiScope'} Capabilities: type: object additionalProperties: false required: [object, key, project_submission, quotes, webhooks, limits, idempotency, authentication] properties: object: {const: capabilities} key: type: object additionalProperties: false required: [environment, scopes] properties: environment: {type: string, enum: [live, test]} scopes: type: array uniqueItems: true items: {$ref: '#/components/schemas/ApiScope'} project_submission: type: object additionalProperties: false required: [enabled, payment_mode, input_modes, delivery_modes] properties: enabled: {type: boolean} payment_mode: {const: invoice_terms} input_modes: type: array items: {type: string, enum: [file, json, text]} delivery_modes: type: array items: {type: string, enum: [file, json, text]} quotes: type: object additionalProperties: false required: [enabled, optional] properties: enabled: {type: boolean} optional: {const: true} webhooks: type: object additionalProperties: false required: [enabled, signature_version, events] properties: enabled: {type: boolean} signature_version: {const: v1} events: type: array items: {$ref: '#/components/schemas/WebhookEventType'} limits: type: object additionalProperties: false required: [requests_per_minute, max_file_bytes, max_inline_content_bytes, max_files_per_project, max_target_languages_per_project] properties: requests_per_minute: {type: integer, minimum: 1} max_file_bytes: {type: integer, minimum: 1} max_inline_content_bytes: {type: integer, minimum: 1} max_files_per_project: {type: integer, minimum: 1} max_target_languages_per_project: {type: integer, minimum: 1} idempotency: type: object additionalProperties: false required: [required_for_mutations, replay_ttl_hours] properties: required_for_mutations: {const: true} replay_ttl_hours: {type: integer, minimum: 1} authentication: type: object additionalProperties: false required: [type, token_exchange_required] properties: type: {const: bearer_api_key} token_exchange_required: {const: false} ApiScope: type: string enum: - account:read - languages:read - files:read - files:write - projects:read - projects:write - deliveries:read - quotes:read - quotes:write - webhooks:read - webhooks:write ServiceOption: type: object additionalProperties: false required: [object, code, name, unit_type] properties: object: {const: service_option} code: {type: string} name: {type: string} unit_type: {type: string} Language: type: object required: [code, name] properties: code: {type: string} name: {type: string} locale: {type: [string, 'null']} script: {type: [string, 'null']} InlineContent: description: Structure-preserving JSON or plain text submitted directly instead of uploaded file IDs. oneOf: - type: object required: [format, value] properties: format: {const: json, description: Preserve the submitted object or array shape in the source and completed delivery.} value: description: JSON object or array whose non-empty string leaves are translated. oneOf: - {type: object} - {type: array} - type: object required: [format, value] properties: format: {const: text, description: Retain the source and completed delivery as plain text.} value: {type: string, minLength: 1, description: Non-empty UTF-8 text to translate.} BillingMetadata: type: object additionalProperties: false properties: po_number: {type: [string, 'null'], maxLength: 191} cost_center: {type: [string, 'null'], maxLength: 191} invoice_notes: {type: [string, 'null'], maxLength: 5000} ProjectInput: type: object additionalProperties: false required: [name, source_language, target_languages] example: name: Catalog SKU 1042 external_id: SKU-1042-ES source_language: EN-US target_languages: [ES-ES] service: translation turnaround: standard instructions: Preserve product codes and JSON property names. content: format: json value: title: Waterproof hiking jacket description: Lightweight shell for wet weather. sku: 1042 active: true metadata: null po_number: PO-2026-1042 cost_center: LOCALIZATION oneOf: - required: [file_ids] - required: [content] properties: name: {type: string, minLength: 1, maxLength: 255, description: Project or quote name displayed in API responses and the 黑料大事记 client portal.} external_id: {type: [string, 'null'], maxLength: 255, description: "Optional correlation ID from your application, scoped to the API key environment."} source_language: {type: string, maxLength: 20, examples: [EN-US], description: Active source language code returned by GET /languages.} target_languages: type: array minItems: 1 maxItems: 50 uniqueItems: true description: Distinct active target language codes, each different from the source language. items: {type: string, maxLength: 20} service: {type: string, default: translation, maxLength: 64, description: Service code returned by GET /service-options.} turnaround: {type: string, enum: [standard, rush, custom], default: standard, description: Requested delivery speed.} due_at: {type: [string, 'null'], format: date-time, description: Optional future requested due time; required by configurations using custom turnaround.} instructions: {type: [string, 'null'], maxLength: 10000, description: Instructions for the translation team.} file_ids: type: array minItems: 1 maxItems: 20 uniqueItems: true description: Ready file IDs returned by POST /files. Use this or content, never both. items: {type: string, pattern: '^file_[A-Za-z0-9_-]{10,64}$'} content: allOf: - {$ref: '#/components/schemas/InlineContent'} description: Inline JSON or text. Use this or file_ids, never both. po_number: {type: [string, 'null'], maxLength: 191, description: Optional purchase-order reference for billing.} cost_center: {type: [string, 'null'], maxLength: 191, description: Optional cost center for billing.} invoice_notes: {type: [string, 'null'], maxLength: 5000, description: Optional billing notes.} QuoteUpdate: type: object additionalProperties: false minProperties: 1 properties: name: {type: string, minLength: 1, maxLength: 255} external_id: {type: [string, 'null'], maxLength: 255} source_language: {type: string, maxLength: 20} target_languages: type: array minItems: 1 maxItems: 50 uniqueItems: true items: {type: string, maxLength: 20} service: {type: string, maxLength: 64} turnaround: {type: string, enum: [standard, rush, custom]} due_at: {type: [string, 'null'], format: date-time} instructions: {type: [string, 'null'], maxLength: 10000} File: type: object required: [id, object, filename, status, analysis, created_at] properties: id: {type: string, pattern: '^file_'} object: {const: file} filename: {type: string} mime_type: {type: [string, 'null']} size: {type: integer, minimum: 0} checksum_sha256: {type: [string, 'null']} status: {type: string, enum: [ready, manual_review]} analysis: type: object additionalProperties: true created_at: {type: string, format: date-time} SourceFile: type: object required: [id, object, filename, status, download_url] properties: id: {type: string, pattern: '^file_'} object: {const: file} filename: {type: string} mime_type: {type: [string, 'null']} size: {type: integer, minimum: 0} status: {type: string, enum: [ready, manual_review]} download_url: {type: string, format: uri} content_url: {type: [string, 'null'], format: uri} Job: type: object required: [id, object, status, progress, delivery_ready] properties: id: {type: string, pattern: '^job_'} object: {const: job} status: {type: string} service: {type: string} source_language: {type: [string, 'null']} target_language: {type: [string, 'null']} progress: {type: number, minimum: 0, maximum: 100} word_count: {type: integer, minimum: 0} delivery_ready: {type: boolean} InvoiceSummary: type: object required: [status, currency, total] properties: status: {type: string} currency: {type: string, minLength: 3, maxLength: 3} total: {type: number, minimum: 0} due_at: {type: [string, 'null'], format: date-time} Project: type: object required: [id, object, name, status, progress, jobs, source_files, delivery_ready, created_at] example: id: proj_01JZ8K6N2W6RX4J9P7Y8K3M2Q1 object: project external_id: SKU-1042-ES name: Catalog SKU 1042 status: new progress: 0 source_language: EN-US target_languages: [ES-ES] source_files: - id: file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2 object: file filename: catalog-sku-1042.json mime_type: application/json size: 142 status: ready download_url: https://apis.stepes.com/v2/files/file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2/download content_url: https://apis.stepes.com/v2/files/file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2/content due_at: null jobs: [] delivery_ready: false invoice: status: Unpaid currency: USD total: 25 due_at: '2026-09-08T00:00:00+00:00' created_at: '2026-08-10T12:00:00+00:00' updated_at: '2026-08-10T12:00:00+00:00' properties: id: {type: string, pattern: '^proj_'} object: {const: project} external_id: {type: [string, 'null']} name: {type: string} status: {type: string} progress: {type: number, minimum: 0, maximum: 100} source_language: {type: [string, 'null']} target_languages: type: array items: {type: string} source_files: type: array items: {$ref: '#/components/schemas/SourceFile'} due_at: {type: [string, 'null'], format: date-time} jobs: type: array items: {$ref: '#/components/schemas/Job'} delivery_ready: {type: boolean} invoice: oneOf: - {$ref: '#/components/schemas/InvoiceSummary'} - {type: 'null'} created_at: {type: string, format: date-time} updated_at: {type: string, format: date-time} Quote: type: object required: [id, object, status, source_files, currency, subtotal, total, created_at] example: id: quote_01JZ8K6N2W6RX4J9P7Y8K3M2Q3 object: quote external_id: SKU-1042-ES status: draft name: Catalog SKU 1042 source_language: EN-US target_languages: [ES-ES] source_files: - id: file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2 object: file filename: catalog-sku-1042.json mime_type: application/json size: 142 status: ready download_url: https://apis.stepes.com/v2/files/file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2/download content_url: https://apis.stepes.com/v2/files/file_01JZ8K6N2W6RX4J9P7Y8K3M2Q2/content currency: USD subtotal: 25 total: 25 expires_at: '2026-09-09T12:00:00+00:00' project_id: null created_at: '2026-08-10T12:00:00+00:00' updated_at: '2026-08-10T12:00:00+00:00' properties: id: {type: string, pattern: '^quote_'} object: {const: quote} external_id: {type: [string, 'null']} status: {type: string, enum: [draft, sent, accepted, cancelled]} name: {type: string} source_language: {type: [string, 'null']} target_languages: type: array items: {type: string} source_files: type: array items: {$ref: '#/components/schemas/SourceFile'} currency: {type: string} subtotal: {type: number} total: {type: number} expires_at: {type: [string, 'null'], format: date-time} project_id: {type: [string, 'null'], pattern: '^proj_'} created_at: {type: string, format: date-time} updated_at: {type: string, format: date-time} Delivery: type: object additionalProperties: true required: [id, object, status] properties: id: {type: string, pattern: '^delivery_'} object: {const: delivery} status: {type: string} format: {type: [string, 'null']} filename: {type: [string, 'null']} download_url: {type: [string, 'null'], format: uri} content_url: {type: [string, 'null'], format: uri} StructuredContent: type: object required: [object, format, content] properties: id: {type: string} object: {type: string, enum: [source_content, delivery_content]} format: {type: string, enum: [json, text]} content: true created_at: {type: [string, 'null'], format: date-time} WebhookInput: type: object additionalProperties: false properties: name: {type: string, minLength: 1, maxLength: 100} url: {type: string, format: uri, pattern: '^https://'} events: type: array minItems: 1 uniqueItems: true items: {$ref: '#/components/schemas/WebhookEventType'} status: {type: string, enum: [active, disabled]} WebhookCreateInput: allOf: - $ref: '#/components/schemas/WebhookInput' - type: object required: [name, url, events] WebhookEventType: type: string enum: - quote.created - quote.updated - quote.submitted - quote.accepted - project.created - project.updated - project.cancelled - project.completed - delivery.ready WebhookEndpoint: type: object required: [id, object, url, events, status, created_at] properties: id: {type: string, pattern: '^wh_'} object: {const: webhook_endpoint} url: {type: string, format: uri} name: {type: string} events: type: array items: {$ref: '#/components/schemas/WebhookEventType'} status: {type: string, enum: [active, disabled, revoked]} created_at: {type: string, format: date-time} updated_at: {type: string, format: date-time} WebhookDelivery: type: object additionalProperties: true required: [id, object, status, event_type] properties: id: {type: string, pattern: '^whd_'} object: {const: webhook_delivery} event_type: {$ref: '#/components/schemas/WebhookEventType'} status: {type: string} attempt_count: {type: integer, minimum: 0} next_attempt_at: {type: [string, 'null'], format: date-time} delivered_at: {type: [string, 'null'], format: date-time} CursorPage: type: object required: [object, data, has_more, next_cursor] properties: object: {const: list} data: {type: array, items: true} has_more: {type: boolean} next_cursor: {type: [string, 'null']} Problem: type: object required: [type, title, status, code, detail, instance, request_id, retryable] properties: type: {type: string, format: uri-reference} title: {type: string} status: {type: integer, minimum: 400, maximum: 599} code: {type: string} detail: {type: string} instance: {type: string, pattern: '^/v2(?:/|$)'} request_id: {type: string, format: uuid} retryable: {type: boolean} errors: type: object additionalProperties: type: array items: {type: string} security: - bearerAuth: []