> ## Documentation Index
> Fetch the complete documentation index at: https://docs.capa.fi/llms.txt
> Use this file to discover all available pages before exploring further.

# Upload Cross-Ramp Invoice

> Uploads the commercial invoice (Base64 PDF) for a cross-ramp in WAITING_INVOICE. On success the cross-ramp moves to PENDING_FUNDS. The response does not include funding instructions: read the cross-ramp to get sourceBankAccount. Naturally idempotent: repeating an upload after it succeeded returns 200 with the current status. This route does not support the Idempotency-Key header. Nothing is paid out for a cross-ramp until its invoice is uploaded, in every country; the payout to the provider is placed after the upload. The file is parsed as a real PDF: an unreadable or encrypted file, or one with 0 or more than 500 pages, is rejected with INVALID_COMMERCIAL_INVOICE (400). For a transaction of a bulk, the stored invoices of the bulk may total at most 24 MiB decoded and 500 pages: a file that would go over is rejected with CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED or CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED (400), nothing is stored and the transaction stays WAITING_INVOICE. A 503 (CROSS_RAMP_BULK_INVOICE_BUSY after a wait of about 2 seconds, or CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE) is temporary and stores nothing: wait a second or two and retry.

Uploads the commercial invoice for a cross-ramp that was created without one (status `WAITING_INVOICE`). On success the cross-ramp moves to `PENDING_FUNDS`. The response returns `id`, `status` and `updatedAt`; read the cross-ramp afterwards to get `sourceBankAccount`, the funding instructions the user needs to deposit the source currency.

> [!NOTE]
>
> The invoice is optional at creation for every country, but nothing is paid out without it. If you did not send `invoiceFile` in [Create Cross-Ramp](https://docs.capa.fi/reference/crossramppartnerv2controller_createpartnercrossramp.md), the cross-ramp waits in `WAITING_INVOICE` and no funding instructions are returned until this call succeeds; the payout to the provider is placed after the upload.

***

## Idempotency

This route does not support the `Idempotency-Key` header. It is naturally idempotent: repeating an upload that already succeeded returns `200` with the current status and creates nothing new.

***

## Rules

* The cross-ramp must be in `WAITING_INVOICE`.
* `invoiceFile`: Base64-encoded PDF, maximum 25 MB once decoded. The file is parsed as a real PDF: an unreadable or encrypted file, or one with 0 or more than 500 pages, is rejected with `INVALID_COMMERCIAL_INVOICE`.
* A valid PDF is accepted automatically (no manual review) and moves the cross-ramp to `PENDING_FUNDS`.
* The user must be verified and have no outstanding beneficial-owner signature; otherwise the request is rejected with `403` and the cross-ramp stays `WAITING_INVOICE`.
* For a transaction of a [bulk](https://docs.capa.fi/docs/cross-ramp.md#upload-bulk-invoices), the stored invoices of the bulk may total at most **24 MiB** decoded and **500 pages**. A file that would go over is rejected with `400` `CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED` (size) or `CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED` (pages); nothing is stored and the transaction stays `WAITING_INVOICE`, so you can retry with a smaller file.
* For a bulk transaction, a `503` (`CROSS_RAMP_BULK_INVOICE_BUSY` or `CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE`) is temporary and nothing is stored. `CROSS_RAMP_BULK_INVOICE_BUSY` means another invoice of the same bulk kept the bulk busy for about 2 seconds: wait a second or two and repeat the upload.
* If storing the file fails you get a retryable `500` and the status stays `WAITING_INVOICE`. Retry with the same file.
* A `WAITING_INVOICE` cross-ramp can also be cancelled with the [cancel endpoint](https://docs.capa.fi/reference/transactionpartnerv2controller_cancelpartnertransaction.md). There is no expiry.
* Replacing an invoice that was already uploaded is not supported.
* There is no dedicated upload webhook event; see [Transaction Events](https://docs.capa.fi/docs/transaction-events.md#cross-ramp-events).

See the [Cross-Ramp guide](https://docs.capa.fi/docs/cross-ramp.md#upload-an-invoice) for the full flow.

***

## Error Codes

### Common Errors

| HTTP Status | Code | Message |
| - | - | - |
| 401 | `UNAUTHORIZED` | "API Key is missing" |
| 401 | `UNAUTHORIZED` | "Invalid API Key format" |
| 401 | `UNAUTHORIZED` | "Invalid API Key" |

### Endpoint-Specific Errors

| HTTP Status | Code | Message |
| - | - | - |
| 400 | `INVALID_USER_INPUT_ERROR` | "Invalid User Input" (`invoiceFile` missing, not valid Base64 or over the size limit) |
| 400 | `INVALID_COMMERCIAL_INVOICE` | "Commercial invoice is invalid: not a valid PDF" (also for an empty or oversized decoded file, "the PDF is encrypted or cannot be read", or "the PDF must have between 1 and 500 pages") |
| 400 | `CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED` | Bulk transaction only: the invoices of the bulk would total more than 24 MiB. Nothing is stored; the transaction stays `WAITING_INVOICE`. Retry with a smaller file |
| 400 | `CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED` | Bulk transaction only: the invoices of the bulk would total more than 500 pages. Nothing is stored; the transaction stays `WAITING_INVOICE`. Retry with a shorter file |
| 403 | `USER_NOT_VERIFIED_ERROR` | The cross-ramp's user is not verified. The cross-ramp stays `WAITING_INVOICE` |
| 403 | `SIGNATURE_REQUIREMENT_NOT_MET` | A beneficial-owner signature is outstanding. The cross-ramp stays `WAITING_INVOICE` |
| 404 | `NOT_FOUND_ERROR` | "Cross ramp {id} was not found" (unknown id or another partner's cross-ramp) |
| 409 | `CROSS_RAMP_NOT_AWAITING_INVOICE` | The cross-ramp is `CANCELLED`, `EXPIRED` or `FAILED`, including when cancelled while uploading |
| 500 | `COMMERCIAL_INVOICE_UPLOAD_FAILED` | Storing the file failed. Retryable, status unchanged |
| 503 | `CROSS_RAMP_BULK_INVOICE_BUSY` | Bulk transaction only: another invoice of the same bulk is being processed. Nothing is stored. Wait a second or two and retry |
| 503 | `CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE` | Bulk transaction only: the size or page count of an invoice already stored for the bulk can't be read yet. Nothing is stored. Back off and retry |


## OpenAPI

````yaml reference/openapi/CrossRampPartnerV2Controller_uploadPartnerCrossRampInvoice.json POST /api/partner/v2/cross-ramp/{id}/invoice
openapi: 3.0.0
info:
  title: Capa Partner API - V2
  description: >-
    Partner API for integrating cryptocurrency on-ramp and off-ramp services
    using Capa's infrastructure. Enable your users to seamlessly convert between
    fiat and crypto.
  version: v2
  contact: {}
servers:
  - url: https://api.sandbox.capa.fi
  - url: https://api.capa.fi
security: []
paths:
  /api/partner/v2/cross-ramp/{id}/invoice:
    post:
      tags:
        - cross-ramp
      summary: Upload Cross-Ramp Invoice
      description: >-
        Uploads the commercial invoice (Base64 PDF) for a cross-ramp in
        WAITING_INVOICE. On success the cross-ramp moves to PENDING_FUNDS. The
        response does not include funding instructions: read the cross-ramp to
        get sourceBankAccount. Naturally idempotent: repeating an upload after
        it succeeded returns 200 with the current status. This route does not
        support the Idempotency-Key header. Nothing is paid out for a cross-ramp
        until its invoice is uploaded, in every country; the payout to the
        provider is placed after the upload. The file is parsed as a real PDF:
        an unreadable or encrypted file, or one with 0 or more than 500 pages,
        is rejected with INVALID_COMMERCIAL_INVOICE (400). For a transaction of
        a bulk, the stored invoices of the bulk may total at most 24 MiB decoded
        and 500 pages: a file that would go over is rejected with
        CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED or
        CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED (400), nothing is stored and the
        transaction stays WAITING_INVOICE. A 503 (CROSS_RAMP_BULK_INVOICE_BUSY
        after a wait of about 2 seconds, or
        CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE) is temporary and stores
        nothing: wait a second or two and retry.
      operationId: CrossRampPartnerV2Controller_uploadPartnerCrossRampInvoice
      parameters:
        - name: id
          in: path
          required: true
          description: Cross-ramp transaction ID returned when the cross-ramp was created.
          schema:
            type: string
            format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                invoiceFile:
                  type: string
                  description: >-
                    Base64-encoded PDF commercial invoice. Maximum 25 MB once
                    decoded. Parsed as a real PDF: an unreadable or encrypted
                    file, or one with 0 or more than 500 pages, is rejected with
                    INVALID_COMMERCIAL_INVOICE.
              required:
                - invoiceFile
              x-readme-ref-name: UploadPartnerCrossRampInvoiceV2RequestBody
      responses:
        '200':
          description: >-
            Invoice accepted. The cross-ramp is now PENDING_FUNDS. Repeating the
            upload after success returns 200 with the current status.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    example: true
                  data:
                    type: object
                    properties:
                      id:
                        type: string
                        description: Cross-ramp transaction ID
                        example: 12a121ad-cbea-4ec4-9e0a-5c861e528bba
                      status:
                        type: string
                        description: >-
                          Cross-ramp status after the upload. Read the
                          cross-ramp to get sourceBankAccount.
                        example: PENDING_FUNDS
                      updatedAt:
                        type: string
                        format: date-time
                        example: '2024-01-01T12:05:00Z'
                      completedAt:
                        type: string
                        format: date-time
                        description: >-
                          Completion timestamp, present only when the cross-ramp
                          is completed.
                        example: '2024-01-01T13:00:00Z'
                    required:
                      - id
                      - status
                      - updatedAt
                    x-readme-ref-name: CrossRampInvoiceUploadResponse
              example:
                success: true
                data:
                  id: 12a121ad-cbea-4ec4-9e0a-5c861e528bba
                  status: PENDING_FUNDS
                  updatedAt: '2024-01-01T12:05:00Z'
        '400':
          description: Bad Request
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                INVALID_USER_INPUT_ERROR:
                  value:
                    success: false
                    code: INVALID_USER_INPUT_ERROR
                    message: Invalid User Input
                    errors:
                      - field: invoiceFile
                        message: '"invoiceFile" must be a valid base64 string'
                INVALID_COMMERCIAL_INVOICE:
                  value:
                    success: false
                    code: INVALID_COMMERCIAL_INVOICE
                    message: 'Commercial invoice is invalid: not a valid PDF'
                INVALID_COMMERCIAL_INVOICE_UNREADABLE:
                  value:
                    success: false
                    code: INVALID_COMMERCIAL_INVOICE
                    message: >-
                      Commercial invoice is invalid: the PDF is encrypted or
                      cannot be read
                INVALID_COMMERCIAL_INVOICE_PAGES:
                  value:
                    success: false
                    code: INVALID_COMMERCIAL_INVOICE
                    message: >-
                      Commercial invoice is invalid: the PDF must have between 1
                      and 500 pages
                CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED:
                  value:
                    success: false
                    code: CROSS_RAMP_BULK_INVOICE_BUDGET_EXCEEDED
                    message: >-
                      The invoices of a bulk may total 25165824 bytes; 20971520
                      are already stored and this one adds 5242880
                CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED:
                  value:
                    success: false
                    code: CROSS_RAMP_BULK_INVOICE_PAGES_EXCEEDED
                    message: >-
                      The invoices of a bulk may total 500 pages; 480 are
                      already stored and this one adds 40
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                UNAUTHORIZED:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: API Key is missing
                UNAUTHORIZED_2:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: Invalid API Key format
                UNAUTHORIZED_3:
                  value:
                    success: false
                    code: UNAUTHORIZED
                    message: Invalid API Key
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                USER_NOT_VERIFIED_ERROR:
                  value:
                    success: false
                    code: USER_NOT_VERIFIED_ERROR
                    message: >-
                      User is not allowed to perform the operations because has
                      not completed the KYC verification.
                SIGNATURE_REQUIREMENT_NOT_MET:
                  value:
                    success: false
                    code: SIGNATURE_REQUIREMENT_NOT_MET
                    message: >-
                      User is not allowed to perform the operation because a
                      required signature is outstanding for BENEFICIAL_OWNER.
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                NOT_FOUND_ERROR:
                  value:
                    success: false
                    code: NOT_FOUND_ERROR
                    message: >-
                      Cross ramp 12a121ad-cbea-4ec4-9e0a-5c861e528bba was not
                      found
        '409':
          description: Conflict
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                CROSS_RAMP_NOT_AWAITING_INVOICE:
                  value:
                    success: false
                    code: CROSS_RAMP_NOT_AWAITING_INVOICE
                    message: >-
                      Cross ramp 12a121ad-cbea-4ec4-9e0a-5c861e528bba is
                      CANCELLED and does not accept an invoice
        '500':
          description: Internal Server Error
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                COMMERCIAL_INVOICE_UPLOAD_FAILED:
                  value:
                    success: false
                    code: COMMERCIAL_INVOICE_UPLOAD_FAILED
                    message: >-
                      Failed to upload commercial invoice for transaction
                      12a121ad-cbea-4ec4-9e0a-5c861e528bba: storage unavailable
                INTERNAL_SERVER_ERROR:
                  value:
                    success: false
                    code: INTERNAL_SERVER_ERROR
                    message: Internal server error
        '503':
          description: >-
            Service Unavailable. Bulk transactions only. Temporary: nothing was
            stored; back off and retry.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
              examples:
                CROSS_RAMP_BULK_INVOICE_BUSY:
                  value:
                    success: false
                    code: CROSS_RAMP_BULK_INVOICE_BUSY
                    message: >-
                      Another invoice of this bulk is being processed; retry in
                      a moment
                CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE:
                  value:
                    success: false
                    code: CROSS_RAMP_BULK_INVOICE_SIZE_UNAVAILABLE
                    message: >-
                      The size of an invoice already stored for this bulk could
                      not be determined; retry in a moment
      security:
        - PartnerApiKey: []
components:
  schemas:
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          example: false
        code:
          type: string
          description: Machine-readable error code.
        message:
          type: string
          description: Human-readable error message.
        errors:
          type: array
          description: Optional per-field validation details.
          items:
            type: object
            properties:
              field:
                type: string
              message:
                type: string
      required:
        - success
        - code
        - message
  securitySchemes:
    PartnerApiKey:
      type: apiKey
      in: header
      name: partner-api-key
      description: API key for the affiliated partner performing the request.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.