openapi: 3.2.0 info: title: Ironfang Finance E-Invoicing Deliveries API version: 1.4.0 summary: Generate UBL invoices and validate Invoice or CreditNote XML with PHIVE. description: 'Ironfang Finance validates UBL e-invoices against the exact EN 16931 and Peppol BIS Billing rule releases published by the standards bodies, and returns a result that names the immutable ruleset it used so the outcome can be reproduced later.' contact: name: Ironfang email: hello@ironfang.uk url: https://ironfang.com/finance termsOfService: https://ironfang.com/legal/terms license: name: Proprietary identifier: LicenseRef-Ironfang-Proprietary servers: - url: https://api.ironfang.com/finance description: Production. Paths below are relative to this product prefix. security: - {} - platformKey: [] tags: - name: Deliveries description: Destinations subscribe to future terminal validation/generation operations in their organisation. paths: /v1/einvoices/destinations: post: operationId: createEinvoiceDestination summary: Create a webhook or S3 destination description: Create a webhook or S3 destination. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '201': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: $ref: '#/components/schemas/DestinationCreated' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' requestBody: required: true description: One JSON object, maximum 16 KiB. Unknown, duplicate and null fields are rejected. Credentials are encrypted and never returned; webhook create/rotate returns its signing secret once. content: application/json: schema: $ref: '#/components/schemas/DestinationCreateRequest' get: operationId: listEinvoiceDestinations summary: List active destination configurations description: List active destination configurations. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: type: object additionalProperties: false required: - destinations properties: destinations: type: array maxItems: 10 items: $ref: '#/components/schemas/Destination' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' /v1/einvoices/destinations/{id}: get: operationId: getEinvoiceDestination summary: Read a destination without its credentials description: Read a destination without its credentials. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: $ref: '#/components/schemas/Destination' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: id in: path required: true schema: type: string format: uuid patch: operationId: updateEinvoiceDestination summary: Enable, disable or rotate destination credentials description: Enable, disable or rotate destination credentials. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: $ref: '#/components/schemas/DestinationCreated' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: id in: path required: true schema: type: string format: uuid requestBody: required: true description: One JSON object, maximum 16 KiB. Unknown, duplicate and null fields are rejected. Credentials are encrypted and never returned; webhook create/rotate returns its signing secret once. content: application/json: schema: $ref: '#/components/schemas/DestinationUpdateRequest' delete: operationId: deleteEinvoiceDestination summary: Retire a destination and erase its stored credentials description: Retire a destination and erase its stored credentials. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '204': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: id in: path required: true schema: type: string format: uuid /v1/einvoices/deliveries: get: operationId: listEinvoiceDeliveries summary: List delivery history with keyset pagination description: List delivery history with keyset pagination. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. Destination, operation and status filters apply before pagination. Pending selects pending deliveries without attempts; retrying selects pending deliveries with at least one attempt. Only deliveries of V1 events are listed here; an operation made through /finance/v2 queues a V2 event, whose deliveries V2 lists at /finance/v2/einvoices/deliveries together with these. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:read responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: type: object additionalProperties: false required: - deliveries - next_cursor properties: deliveries: type: array maxItems: 100 items: $ref: '#/components/schemas/Delivery' next_cursor: type: string '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: destination in: query schema: type: string format: uuid - name: operation_id in: query schema: type: string format: uuid - name: status in: query schema: type: string enum: - pending - retrying - delivering - delivered - failed - name: cursor in: query schema: type: string maxLength: 256 - name: limit in: query schema: type: integer minimum: 1 maximum: 100 default: 50 /v1/einvoices/deliveries/{id}: get: operationId: getEinvoiceDelivery summary: Read a delivery and its immutable attempt history description: Read a delivery and its immutable attempt history. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:read responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: $ref: '#/components/schemas/DeliveryDetail' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: id in: path required: true schema: type: string format: uuid /v1/einvoices/deliveries/{id}/retry: post: operationId: retryEinvoiceDelivery summary: Retry failed delivery without rerunning validation description: Retry failed delivery without rerunning validation. Requires the listed API-key scope. See the deliveries tag for event, signature, retry, storage and retention semantics. Invoice validation and usage are unchanged by delivery. tags: - Deliveries security: - platformKey: [] x-ironfang-scopes: - finance:einvoices:destinations:manage responses: '200': description: 'Success. All responses use Cache-Control: no-store.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/json: schema: $ref: '#/components/schemas/DeliveryDetail' '400': $ref: '#/components/responses/MalformedRequest' '401': $ref: '#/components/responses/Unauthenticated' '403': $ref: '#/components/responses/InsufficientScope' '404': $ref: '#/components/responses/NotFound' '429': $ref: '#/components/responses/DeliveryRateLimited' '500': $ref: '#/components/responses/ReadInternalError' '503': $ref: '#/components/responses/DeliveryUnavailable' parameters: - name: id in: path required: true schema: type: string format: uuid components: schemas: DeliveryEvent: type: object additionalProperties: false required: - schema - id - type - created_at - state_version - data properties: schema: type: string const: financewolf/einvoice/event/v1 id: type: string format: uuid type: type: string enum: - einvoice.validation.completed - einvoice.generation.completed - einvoice.operation.failed created_at: type: string format: date-time state_version: type: integer const: 1 data: type: object additionalProperties: false required: - operation_id - operation - status - outcome - input_sha256 - usage_charged - artifacts properties: operation_id: type: string format: uuid operation: type: string enum: - validate - generate status: type: string enum: - completed - error outcome: type: string enum: - valid - invalid - indeterminate failure_code: type: string ruleset_id: type: string input_sha256: $ref: '#/components/schemas/SHA256' usage_charged: type: boolean job_id: type: string format: uuid batch_id: type: string format: uuid result_url: type: string format: uri-reference artifacts: type: array maxItems: 2 items: $ref: '#/components/schemas/DeliveryArtifact' BillingRefusal: type: object description: 'On a billing refusal only: the product and meter the billing account refused, and when the free allowance renews (the start of the next UTC month) where that is the reason.' additionalProperties: false properties: product: type: string enum: - finance meter: type: string enum: - finance.validation - finance.generation reset_at: type: string format: date-time DestinationCredentials: type: object additionalProperties: false required: - access_key - secret_key properties: access_key: type: string minLength: 1 maxLength: 256 writeOnly: true secret_key: type: string minLength: 1 maxLength: 512 writeOnly: true session_token: type: string maxLength: 8192 writeOnly: true RequestID: type: string pattern: ^[A-Za-z0-9_-]{8,64}$ DeliveryDetail: type: object additionalProperties: false required: - id - event_id - operation_id - destination_id - status - attempts - max_attempts - created_at - expires_at - next_attempt_at - event - history properties: id: type: string format: uuid event_id: type: string format: uuid operation_id: type: string format: uuid destination_id: type: string format: uuid status: type: string enum: - pending - delivering - delivered - failed attempts: type: integer minimum: 0 maximum: 32 max_attempts: type: integer minimum: 1 maximum: 32 failure_code: type: string enum: - destination_unavailable - credentials_unavailable - network_error - http_rejected - storage_rejected - object_conflict - result_unavailable - internal_error - lease_expired - event_expired http_status: type: integer minimum: 1 maximum: 599 created_at: type: string format: date-time expires_at: type: string format: date-time finished_at: type: string format: date-time next_attempt_at: type: string format: date-time description: Scheduled time for pending work; ignore for terminal deliveries. event: $ref: '#/components/schemas/DeliveryEvent' history: type: array maxItems: 32 items: $ref: '#/components/schemas/DeliveryAttempt' DeliveryArtifact: type: object additionalProperties: false required: - name - content_type - sha256 - bytes properties: name: type: string enum: - result.json - document.xml content_type: type: string enum: - application/json - application/xml sha256: $ref: '#/components/schemas/SHA256' bytes: type: integer minimum: 1 DestinationCreated: type: object additionalProperties: false required: - id - type - name - config - enabled - created_at - schema properties: id: type: string format: uuid type: type: string enum: - webhook - s3 name: type: string minLength: 1 maxLength: 100 config: $ref: '#/components/schemas/DestinationConfig' enabled: type: boolean created_at: type: string format: date-time retired_at: type: string format: date-time schema: type: string const: financewolf/einvoice/destination/v1 signing_secret: type: string pattern: ^[0-9a-f]{64}$ description: One-time hex-encoded 32-byte HMAC secret. Decode hex before verifying signatures. Delivery: type: object additionalProperties: false required: - id - event_id - operation_id - destination_id - status - attempts - max_attempts - created_at - expires_at - next_attempt_at - event properties: id: type: string format: uuid event_id: type: string format: uuid operation_id: type: string format: uuid destination_id: type: string format: uuid status: type: string enum: - pending - delivering - delivered - failed attempts: type: integer minimum: 0 maximum: 32 max_attempts: type: integer minimum: 1 maximum: 32 failure_code: type: string enum: - destination_unavailable - credentials_unavailable - network_error - http_rejected - storage_rejected - object_conflict - result_unavailable - internal_error - lease_expired - event_expired http_status: type: integer minimum: 1 maximum: 599 created_at: type: string format: date-time expires_at: type: string format: date-time finished_at: type: string format: date-time next_attempt_at: type: string format: date-time description: Scheduled time for pending work; ignore for terminal deliveries. event: $ref: '#/components/schemas/DeliveryEvent' OpaqueID: type: string description: An opaque Ironfang identifier. minLength: 1 maxLength: 64 pattern: ^[A-Za-z0-9_-]+$ DestinationCreateRequest: type: object additionalProperties: false required: - type - name - config properties: type: type: string enum: - webhook - s3 name: type: string minLength: 1 maxLength: 100 config: $ref: '#/components/schemas/DestinationConfig' credentials: $ref: '#/components/schemas/DestinationCredentials' DestinationUpdateRequest: type: object additionalProperties: false required: [] properties: enabled: type: boolean rotate_secret: type: boolean credentials: $ref: '#/components/schemas/DestinationCredentials' minProperties: 1 Problem: type: object description: An RFC 9457 problem. `code` is the stable, machine-readable Ironfang identifier; `type` is its URL and `status` its one HTTP status, both fixed per code below. `detail` is safe to show and never carries parser output, invoice content or stack traces. Validation findings are never Problems. additionalProperties: false required: - type - title - status - detail - code - request_id properties: type: type: string format: uri pattern: ^https://ironfang\.com/problems/[a-z_]+$ title: type: string minLength: 1 maxLength: 128 status: type: integer minimum: 400 maximum: 599 detail: type: string minLength: 1 maxLength: 512 instance: type: string format: uri-reference maxLength: 256 code: type: string description: The stable Ironfang problem code. enum: - malformed_request - unauthenticated - insufficient_scope - idempotency_conflict - payload_too_large - unsupported_content_type - unknown_ruleset - ruleset_disabled - result_gone - unsupported_profile - profile_undetected - unsupported_document_type - not_found - rate_limited - quota_exhausted - billing_moved - free_allowance_exhausted - account_budget_exhausted - product_budget_exhausted - exemption_limit_reached - paid_usage_paused - payment_required - payment_action_required - account_restricted - account_closed - product_not_eligible - billing_temporarily_unavailable - validation_timeout - validator_unavailable - jobs_unavailable - delivery_unavailable - generation_failed - report_unavailable - report_incomplete - render_unavailable - render_timeout - internal_error request_id: $ref: '#/components/schemas/RequestID' errors: type: array description: Field-level errors, on `malformed_request` only. Bounded; empty is omitted. minItems: 1 maxItems: 50 items: $ref: '#/components/schemas/FieldError' operation_id: $ref: '#/components/schemas/OpaqueID' description: On an indeterminate validation problem only, the operation record that was opened, if any. outcome: type: string const: indeterminate usage_charged: type: boolean const: false retry_after_seconds: type: integer minimum: 1 maximum: 3600 description: Only on problems that invite a retry (`rate_limited`, `quota_exhausted`, `validator_unavailable`, `billing_temporarily_unavailable`). billing: $ref: '#/components/schemas/BillingRefusal' allOf: - if: properties: code: const: malformed_request then: properties: status: const: 400 type: const: https://ironfang.com/problems/malformed_request - if: properties: code: const: unauthenticated then: properties: status: const: 401 type: const: https://ironfang.com/problems/unauthenticated - if: properties: code: const: insufficient_scope then: properties: status: const: 403 type: const: https://ironfang.com/problems/insufficient_scope - if: properties: code: const: not_found then: properties: status: const: 404 type: const: https://ironfang.com/problems/not_found - if: properties: code: const: idempotency_conflict then: properties: status: const: 409 type: const: https://ironfang.com/problems/idempotency_conflict - if: properties: code: const: result_gone then: properties: status: const: 410 type: const: https://ironfang.com/problems/result_gone - if: properties: code: const: ruleset_disabled then: properties: status: const: 410 type: const: https://ironfang.com/problems/ruleset_disabled - if: properties: code: const: payload_too_large then: properties: status: const: 413 type: const: https://ironfang.com/problems/payload_too_large - if: properties: code: const: unsupported_content_type then: properties: status: const: 415 type: const: https://ironfang.com/problems/unsupported_content_type - if: properties: code: const: unknown_ruleset then: properties: status: const: 422 type: const: https://ironfang.com/problems/unknown_ruleset - if: properties: code: const: unsupported_profile then: properties: status: const: 422 type: const: https://ironfang.com/problems/unsupported_profile - if: properties: code: const: profile_undetected then: properties: status: const: 422 type: const: https://ironfang.com/problems/profile_undetected - if: properties: code: const: unsupported_document_type then: properties: status: const: 422 type: const: https://ironfang.com/problems/unsupported_document_type - if: properties: code: const: rate_limited then: properties: status: const: 429 type: const: https://ironfang.com/problems/rate_limited - if: properties: code: const: billing_moved then: properties: status: const: 410 type: const: https://ironfang.com/problems/billing_moved - if: properties: code: const: free_allowance_exhausted then: properties: status: const: 429 type: const: https://ironfang.com/problems/free_allowance_exhausted - if: properties: code: const: account_budget_exhausted then: properties: status: const: 429 type: const: https://ironfang.com/problems/account_budget_exhausted - if: properties: code: const: product_budget_exhausted then: properties: status: const: 429 type: const: https://ironfang.com/problems/product_budget_exhausted - if: properties: code: const: exemption_limit_reached then: properties: status: const: 429 type: const: https://ironfang.com/problems/exemption_limit_reached - if: properties: code: const: paid_usage_paused then: properties: status: const: 402 type: const: https://ironfang.com/problems/paid_usage_paused - if: properties: code: const: payment_required then: properties: status: const: 402 type: const: https://ironfang.com/problems/payment_required - if: properties: code: const: payment_action_required then: properties: status: const: 402 type: const: https://ironfang.com/problems/payment_action_required - if: properties: code: const: account_restricted then: properties: status: const: 402 type: const: https://ironfang.com/problems/account_restricted - if: properties: code: const: account_closed then: properties: status: const: 410 type: const: https://ironfang.com/problems/account_closed - if: properties: code: const: product_not_eligible then: properties: status: const: 403 type: const: https://ironfang.com/problems/product_not_eligible - if: properties: code: const: billing_temporarily_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/billing_temporarily_unavailable - if: properties: code: const: quota_exhausted then: properties: status: const: 429 type: const: https://ironfang.com/problems/quota_exhausted - if: properties: code: const: report_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/report_unavailable - if: properties: code: const: report_incomplete then: properties: status: const: 422 type: const: https://ironfang.com/problems/report_incomplete - if: properties: code: const: render_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/render_unavailable - if: properties: code: const: render_timeout then: properties: status: const: 504 type: const: https://ironfang.com/problems/render_timeout - if: properties: code: const: generation_failed then: required: - outcome - usage_charged properties: status: const: 500 type: const: https://ironfang.com/problems/generation_failed - if: properties: code: const: internal_error then: properties: status: const: 500 type: const: https://ironfang.com/problems/internal_error - if: properties: code: const: delivery_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/delivery_unavailable - if: properties: code: const: jobs_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/jobs_unavailable - if: properties: code: const: validator_unavailable then: properties: status: const: 503 type: const: https://ironfang.com/problems/validator_unavailable - if: properties: code: const: validation_timeout then: properties: status: const: 504 type: const: https://ironfang.com/problems/validation_timeout - if: properties: code: enum: - validation_timeout - validator_unavailable then: required: - outcome - usage_charged - if: not: properties: code: enum: - validation_timeout - validator_unavailable - internal_error - generation_failed then: not: anyOf: - required: - outcome - required: - usage_charged - required: - operation_id - if: anyOf: - required: - outcome - required: - usage_charged - required: - operation_id then: required: - outcome - usage_charged - if: required: - errors then: properties: code: const: malformed_request - if: required: - retry_after_seconds then: properties: code: enum: - rate_limited - quota_exhausted - validator_unavailable - jobs_unavailable - delivery_unavailable - billing_temporarily_unavailable - if: required: - billing then: properties: code: enum: - free_allowance_exhausted - account_budget_exhausted - product_budget_exhausted - exemption_limit_reached - paid_usage_paused - payment_required - payment_action_required - account_restricted - account_closed - product_not_eligible - billing_temporarily_unavailable DestinationConfig: type: object additionalProperties: false required: [] properties: url: type: string format: uri maxLength: 2048 endpoint: type: string format: uri maxLength: 2048 region: type: string maxLength: 63 bucket: type: string maxLength: 63 prefix: type: string maxLength: 200 path_style: type: boolean FieldError: type: object additionalProperties: false required: - field - code - message properties: field: type: string description: The option or parameter at fault, e.g. `ruleset`, `options.document_type`. minLength: 1 maxLength: 128 code: type: string enum: - required - invalid_value - unknown_field - too_long message: type: string minLength: 1 maxLength: 256 Destination: type: object additionalProperties: false required: - id - type - name - config - enabled - created_at properties: id: type: string format: uuid type: type: string enum: - webhook - s3 name: type: string minLength: 1 maxLength: 100 config: $ref: '#/components/schemas/DestinationConfig' enabled: type: boolean created_at: type: string format: date-time retired_at: type: string format: date-time SHA256: type: string description: Lowercase hex SHA-256. pattern: ^[0-9a-f]{64}$ DeliveryAttempt: type: object additionalProperties: false required: - attempt - started_at properties: attempt: type: integer minimum: 1 maximum: 32 started_at: type: string format: date-time finished_at: type: string format: date-time http_status: type: integer minimum: 1 maximum: 599 failure_code: type: string responses: DeliveryRateLimited: description: Delivery management failed; the invoice outcome is unchanged. headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' Retry-After: $ref: '#/components/headers/RetryAfter' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - rate_limited - quota_exhausted status: const: 429 not: anyOf: - required: - outcome - required: - usage_charged - required: - operation_id DeliveryUnavailable: description: Delivery management failed; the invoice outcome is unchanged. headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' Retry-After: $ref: '#/components/headers/RetryAfter' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - delivery_unavailable status: const: 503 not: anyOf: - required: - outcome - required: - usage_charged - required: - operation_id NotFound: description: No such ruleset visible to this caller (unknown, an internal candidate, or the keyword `latest`). headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - not_found status: const: 404 MalformedRequest: description: The request itself is wrong - not the document being validated. headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - malformed_request status: const: 400 examples: field-errors: summary: Bad option values externalValue: https://api.ironfang.com/finance/examples/v1-problem-field-errors.json ReadInternalError: description: 'Ironfang Finance failed while reading the registry. Not a validation verdict: the body carries no outcome or usage fields.' headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - internal_error status: const: 500 not: anyOf: - required: - outcome - required: - usage_charged - required: - operation_id InsufficientScope: description: The key is valid but does not carry the scope this operation needs. headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - insufficient_scope status: const: 403 Unauthenticated: description: A credential was presented and could not be verified. Anonymous access, where permitted, sends no credential at all. headers: X-Ironfang-Request-ID: $ref: '#/components/headers/XIronfangRequestID' X-Request-ID: $ref: '#/components/headers/XRequestIDEcho' content: application/problem+json: schema: allOf: - $ref: '#/components/schemas/Problem' - properties: code: enum: - unauthenticated status: const: 401 headers: XIronfangRequestID: description: Ironfang's internal request id, minted at the edge for every request and carried in every Problem body as `request_id`. Quote it in support requests. schema: $ref: '#/components/schemas/RequestID' XRequestIDEcho: description: 'Your own correlation id, echoed back when the request carried a well-formed `X-Request-ID`: visible ASCII only (bytes 0x21 to 0x7E, so no spaces or control characters), 1 to 128 bytes. Anything else is ignored, not echoed. Never used as Ironfang''s identifier for the request.' required: false schema: type: string minLength: 1 maxLength: 128 pattern: ^[\x21-\x7E]{1,128}$ RetryAfter: description: Seconds to wait before retrying. Mirrors `retry_after_seconds` in the body. schema: type: integer minimum: 1 securitySchemes: platformKey: type: http scheme: bearer description: An Ironfang platform API key minted in the portal. Scopes listed on an operation are the ones the key must carry. Keys are the only credential this boundary accepts in V1. externalDocs: description: Ironfang Finance documentation url: https://ironfang.com/docs/finance