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

# Finalize an Invoice

> Issue a draft invoice, and optionally email it to the customer in the same call.



## OpenAPI

````yaml post /billing/invoices/{invoice_id}/finalize
openapi: 3.1.0
info:
  title: public
  description: ''
  license:
    name: Apache 2.0
    url: https://www.apache.org/licenses/LICENSE-2.0
  version: 1.122.7
servers:
  - url: https://test.dodopayments.com/
    description: Test Mode Server Host
  - url: https://live.dodopayments.com/
    description: Live Mode Server Host
security: []
tags:
  - name: Products
  - name: Payments
  - name: Subscriptions
  - name: Addons
  - name: Customers
  - name: Refunds
  - name: Disputes
  - name: Events
  - name: License Keys
  - name: Entitlements
  - name: Licenses
  - name: Discounts
  - name: Meters
  - name: Credit Entitlements
  - name: Credit Entitlement Balances
  - name: Outgoing Webhooks
  - name: Checkout
  - name: Webhook Events
  - name: Payment Connector Webhooks
  - name: Moderation
  - name: Invoices
  - name: Workload Identity
paths:
  /billing/invoices/{invoice_id}/finalize:
    post:
      tags:
        - Invoices
      summary: Finalize an invoice
      description: >-
        Issues the draft. With `send: true`, the invoice email goes out after
        the issue.

        A failed send keeps the invoice issued. Call `/send` again with the new
        `ETag`.
      operationId: finalize_invoice
      parameters:
        - name: invoice_id
          in: path
          description: Invoice ID
          required: true
          schema:
            type: string
        - name: If-Match
          in: header
          description: The row_version of the invoice that the request changes.
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/FinalizeInvoiceRequest'
        required: true
      responses:
        '200':
          description: ''
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/InvoiceResponse'
        '400':
          description: >-
            The If-Match header or a field is not valid
            (InvalidRequestParameters).
        '404':
          description: The invoice does not exist (NotFound).
        '409':
          description: The invoice changed (InvoiceVersionConflict).
        '422':
          description: >-
            The invoice is not a draft (InvoiceTransitionNotAllowed). The
            billing address or the tax ID is missing, the due_at is past, or the
            invoice breaks another invoice rule (InvalidRequestBody).
        '500':
          description: Something went wrong :(
      security:
        - API_KEY: []
      x-codeSamples:
        - lang: JavaScript
          source: >-
            import DodoPayments from 'dodopayments';


            const client = new DodoPayments({
              bearerToken: process.env['DODO_PAYMENTS_API_KEY'], // This is the default and can be omitted
            });


            const invoice = await client.invoices.finalize('invoice_id', {
            'If-Match': 'If-Match' });


            console.log(invoice.amount_paid);
        - lang: Python
          source: |-
            import os
            from dodopayments import DodoPayments

            client = DodoPayments(
                bearer_token=os.environ.get("DODO_PAYMENTS_API_KEY"),  # This is the default and can be omitted
            )
            invoice = client.invoices.finalize(
                invoice_id="invoice_id",
                if_match="If-Match",
            )
            print(invoice.amount_paid)
        - lang: Go
          source: "package main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\n\t\"github.com/dodopayments/dodopayments-go\"\n\t\"github.com/dodopayments/dodopayments-go/option\"\n)\n\nfunc main() {\n\tclient := dodopayments.NewClient(\n\t\toption.WithBearerToken(\"My Bearer Token\"),\n\t)\n\tinvoice, err := client.Invoices.Finalize(\n\t\tcontext.TODO(),\n\t\t\"invoice_id\",\n\t\tdodopayments.InvoiceFinalizeParams{\n\t\t\tIfMatch: dodopayments.F(\"If-Match\"),\n\t\t},\n\t)\n\tif err != nil {\n\t\tpanic(err.Error())\n\t}\n\tfmt.Printf(\"%+v\\n\", invoice.AmountPaid)\n}\n"
        - lang: Java
          source: |-
            package com.dodopayments.api.example;

            import com.dodopayments.api.client.DodoPaymentsClient;
            import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient;
            import com.dodopayments.api.models.invoices.Invoice;
            import com.dodopayments.api.models.invoices.InvoiceFinalizeParams;

            public final class Main {
                private Main() {}

                public static void main(String[] args) {
                    DodoPaymentsClient client = DodoPaymentsOkHttpClient.fromEnv();

                    InvoiceFinalizeParams params = InvoiceFinalizeParams.builder()
                        .invoiceId("invoice_id")
                        .ifMatch("If-Match")
                        .build();
                    Invoice invoice = client.invoices().finalize(params);
                }
            }
        - lang: Kotlin
          source: |-
            package com.dodopayments.api.example

            import com.dodopayments.api.client.DodoPaymentsClient
            import com.dodopayments.api.client.okhttp.DodoPaymentsOkHttpClient
            import com.dodopayments.api.models.invoices.Invoice
            import com.dodopayments.api.models.invoices.InvoiceFinalizeParams

            fun main() {
                val client: DodoPaymentsClient = DodoPaymentsOkHttpClient.fromEnv()

                val params: InvoiceFinalizeParams = InvoiceFinalizeParams.builder()
                    .invoiceId("invoice_id")
                    .ifMatch("If-Match")
                    .build()
                val invoice: Invoice = client.invoices().finalize(params)
            }
        - lang: Ruby
          source: >-
            require "dodopayments"


            dodo_payments = Dodopayments::Client.new(
              bearer_token: "My Bearer Token",
              environment: "test_mode" # defaults to "live_mode"
            )


            invoice = dodo_payments.invoices.finalize("invoice_id", if_match:
            "If-Match")


            puts(invoice)
        - lang: PHP
          source: |-
            <?php

            require_once dirname(__DIR__) . '/vendor/autoload.php';

            use Dodopayments\Client;
            use Dodopayments\Core\Exceptions\APIException;

            $client = new Client(
              bearerToken: getenv('DODO_PAYMENTS_API_KEY') ?: 'My Bearer Token',
              environment: 'test_mode',
            );

            try {
              $invoice = $client->invoices->finalize(
                'invoice_id',
                ifMatch: 'If-Match',
                ccEmails: ['string'],
                customerEmail: 'customer_email',
                send: true,
              );

              var_dump($invoice);
            } catch (APIException $e) {
              echo $e->getMessage();
            }
        - lang: C#
          source: |-
            using System;
            using DodoPayments.Client;
            using DodoPayments.Client.Models.Invoices;

            DodoPaymentsClient client = new();

            InvoiceFinalizeParams parameters = new()
            {
                InvoiceID = "invoice_id",
                IfMatch = "If-Match",
            };

            var invoice = await client.Invoices.Finalize(parameters);

            Console.WriteLine(invoice);
        - lang: Rust
          source: |-
            use dodopayments::Client;

            #[tokio::main]
            async fn main() -> dodopayments::Result<()> {
                let client = Client::from_env()?;
                let invoice_id = "invoice_id";
                let result = client
                    .invoices()
                    .finalize()
                    .invoice_id(invoice_id)
                    .body(Default::default())
                    .await?;
                println!("{result:?}");
                Ok(())
            }
components:
  schemas:
    FinalizeInvoiceRequest:
      type: object
      properties:
        cc_emails:
          type:
            - array
            - 'null'
          items:
            type: string
          description: 10 addresses or fewer.
        customer_email:
          type:
            - string
            - 'null'
        send:
          type: boolean
          description: '`true` sends the invoice email after finalise.'
      additionalProperties: false
    InvoiceResponse:
      type: object
      description: >-
        An invoice-led invoice. Every read and every `invoice.*` webhook uses
        this schema.
      required:
        - invoice_id
        - business_id
        - status
        - billing_mode
        - currency
        - customer
        - created_at
        - metadata
        - row_version
        - tax
        - credits
        - total_amount
        - discount_ids
        - amount_paid
        - amount_refunded
        - amount_due
        - tags
        - retry_count
        - editable_fields
        - allowed_actions
        - subscription_ids
        - refund_ids
        - frequency
      properties:
        allowed_actions:
          type: array
          items:
            $ref: '#/components/schemas/MerchantAction'
          description: The actions that the current status accepts.
        amount_due:
          type: integer
          format: int64
          description: >-
            The amount that the customer must pay. Zero unless the invoice is
            open or past due.
        amount_paid:
          type: integer
          format: int64
          description: >-
            The sum of the succeeded payments, in the smallest currency unit. A
            late payment is not included after its late refund.
        amount_refunded:
          type: integer
          format: int64
          description: >-
            The sum of the succeeded refunds, in the currency of each payment.
            The late refund of a late payment is not included.
        billing_mode:
          $ref: '#/components/schemas/BillingMode'
        business_id:
          type: string
        collection_method:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/CollectionMethod'
        created_at:
          type: string
          format: date-time
        credits:
          type: integer
          format: int64
          description: >-
            Customer credits applied at finalise, in the smallest currency unit.
            Zero or less.
        currency:
          $ref: '#/components/schemas/Currency'
        customer:
          $ref: '#/components/schemas/InvoiceCustomer'
        discount_ids:
          type: array
          items:
            type: string
          description: The discount codes of the invoice.
        due_at:
          type:
            - string
            - 'null'
          format: date-time
        dunning_state:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/DunningState'
              description: >-
                `null` for an invoice that has no collection: draft, paid, void
                or uncollectable.
        editable_fields:
          type: array
          items:
            $ref: '#/components/schemas/InvoiceField'
          description: The fields that `PATCH` can change in the current status.
        finalized_at:
          type:
            - string
            - 'null'
          format: date-time
        frequency:
          $ref: '#/components/schemas/InvoiceFrequency'
        hosted_url:
          type:
            - string
            - 'null'
          description: The page where the customer pays. `null` until the invoice is sent.
        invoice_id:
          type: string
        lines:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/InvoiceLine'
          description: Only on a single invoice. A list leaves it out.
        memo:
          type:
            - string
            - 'null'
        metadata:
          type: object
        next_reminder_at:
          type:
            - string
            - 'null'
          format: date-time
          description: >-
            The time of the next reminder email to the customer, before or after
            the due date.

            `null` when no reminder email will go out.
        next_retry_at:
          type:
            - string
            - 'null'
          format: date-time
        payment_terms_days:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            Days from finalise to the due date. `null` when the invoice has a
            custom due date.
        payments:
          type:
            - array
            - 'null'
          items:
            $ref: '#/components/schemas/InvoicePayment'
          description: Only on a single invoice. A list leaves it out.
        pdf_url:
          type:
            - string
            - 'null'
        refund_ids:
          type: array
          items:
            type: string
        reminder_settings:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/ReminderSettings'
              description: >-
                `null` on a draft that keeps all reminder settings of the
                business.
        retry_count:
          type: integer
          format: int32
          description: The number of failed automatic charges.
        review_deadline:
          type:
            - string
            - 'null'
          format: date-time
          description: The time at which a draft that waits for review finalises.
        row_version:
          type: integer
          format: int64
          description: >-
            Goes up by one on each change. Use it to ignore an older webhook
            delivery.
        sent_at:
          type:
            - string
            - 'null'
          format: date-time
        status:
          $ref: '#/components/schemas/InvoiceStatus'
        subscription_ids:
          type: array
          items:
            type: string
        tags:
          type: array
          items:
            $ref: '#/components/schemas/InvoiceTag'
        tax:
          type: integer
          format: int32
          description: Tax in the smallest currency unit.
        total_amount:
          type: integer
          format: int32
          description: Total with tax, before credits, in the smallest currency unit.
    MerchantAction:
      type: string
      description: >-
        An action that a merchant can request on the invoice in its current
        status.
      enum:
        - edit
        - finalize
        - delete
        - send
        - retry
        - void
        - mark_uncollectable
        - change_dunning
        - add_note
        - duplicate
    BillingMode:
      type: string
      enum:
        - normal
        - invoice_led
    CollectionMethod:
      type: string
      enum:
        - auto_charge
        - manual
    Currency:
      type: string
      enum:
        - AED
        - ALL
        - AMD
        - ANG
        - AOA
        - ARS
        - AUD
        - AWG
        - AZN
        - BAM
        - BBD
        - BDT
        - BGN
        - BHD
        - BIF
        - BMD
        - BND
        - BOB
        - BRL
        - BSD
        - BWP
        - BYN
        - BZD
        - CAD
        - CHF
        - CLP
        - CNY
        - COP
        - CRC
        - CUP
        - CVE
        - CZK
        - DJF
        - DKK
        - DOP
        - DZD
        - EGP
        - ETB
        - EUR
        - FJD
        - FKP
        - GBP
        - GEL
        - GHS
        - GIP
        - GMD
        - GNF
        - GTQ
        - GYD
        - HKD
        - HNL
        - HRK
        - HTG
        - HUF
        - IDR
        - ILS
        - INR
        - IQD
        - JMD
        - JOD
        - JPY
        - KES
        - KGS
        - KHR
        - KMF
        - KRW
        - KWD
        - KYD
        - KZT
        - LAK
        - LBP
        - LKR
        - LRD
        - LSL
        - LYD
        - MAD
        - MDL
        - MGA
        - MKD
        - MMK
        - MNT
        - MOP
        - MRU
        - MUR
        - MVR
        - MWK
        - MXN
        - MYR
        - MZN
        - NAD
        - NGN
        - NIO
        - NOK
        - NPR
        - NZD
        - OMR
        - PAB
        - PEN
        - PGK
        - PHP
        - PKR
        - PLN
        - PYG
        - QAR
        - RON
        - RSD
        - RUB
        - RWF
        - SAR
        - SBD
        - SCR
        - SEK
        - SGD
        - SHP
        - SLE
        - SLL
        - SOS
        - SRD
        - SSP
        - STN
        - SVC
        - SZL
        - THB
        - TND
        - TOP
        - TRY
        - TTD
        - TWD
        - TZS
        - UAH
        - UGX
        - USD
        - UYU
        - UZS
        - VES
        - VND
        - VUV
        - WST
        - XAF
        - XCD
        - XOF
        - XPF
        - YER
        - ZAR
        - ZMW
    InvoiceCustomer:
      type: object
      required:
        - customer_id
        - cc_emails
        - billing_address
      properties:
        billing_address:
          $ref: '#/components/schemas/InvoiceBillingAddress'
        cc_emails:
          type: array
          items:
            type: string
        customer_id:
          type: string
        email:
          type:
            - string
            - 'null'
        tax_id:
          type:
            - string
            - 'null'
    DunningState:
      type: string
      enum:
        - not_started
        - active
        - paused
        - exhausted
    InvoiceField:
      type: string
      enum:
        - customer
        - items
        - discounts
        - currency
        - billing_address
        - tax_id
        - review_required
        - due_at
        - collection_method
        - memo
        - customer_email
        - cc_emails
        - dunning
        - metadata
    InvoiceFrequency:
      oneOf:
        - type: object
          title: One Time
          required:
            - type
          properties:
            type:
              type: string
              enum:
                - one_time
              x-stainless-const: true
        - type: object
          title: Recurring
          required:
            - count
            - interval
            - type
          properties:
            count:
              type: integer
              format: int32
            interval:
              $ref: '#/components/schemas/TimeInterval'
            type:
              type: string
              enum:
                - recurring
              x-stainless-const: true
        - type: object
          title: Mixed
          required:
            - type
          properties:
            type:
              type: string
              enum:
                - mixed
              x-stainless-const: true
      description: >-
        How often the invoice lines bill. `mixed` covers several intervals, or
        one-time lines next to a plan.
      discriminator:
        propertyName: type
    InvoiceLine:
      type: object
      description: One frozen line. Amounts are in the smallest currency unit.
      required:
        - kind
        - quantity
        - unit_amount
        - tax
        - tax_inclusive
        - amount
      properties:
        addon_id:
          type:
            - string
            - 'null'
        amount:
          type: integer
          format: int64
        description:
          type:
            - string
            - 'null'
        kind:
          $ref: '#/components/schemas/LineKind'
        name:
          type:
            - string
            - 'null'
        period_end:
          type:
            - string
            - 'null'
          format: date-time
        period_start:
          type:
            - string
            - 'null'
          format: date-time
        product_id:
          type:
            - string
            - 'null'
        quantity:
          type: integer
          format: int32
          description: >-
            A usage line has a quantity of 1. Its amount is the full usage
            charge.
        subscription_id:
          type:
            - string
            - 'null'
        tax:
          type: integer
          format: int64
        tax_inclusive:
          type: boolean
          description: '`true` when `amount` includes `tax`.'
        tax_rate:
          type:
            - integer
            - 'null'
          format: int32
          description: Tax percent times 100. For example, 1800 is 18%.
        unit_amount:
          type: integer
          format: int64
    InvoicePayment:
      type: object
      required:
        - payment_id
        - amount
        - created_at
      properties:
        amount:
          type: integer
          format: int64
        created_at:
          type: string
          format: date-time
        payment_id:
          type: string
        retry_attempt:
          type:
            - integer
            - 'null'
          format: int32
          description: >-
            The automatic charge number. `null` for a payment that the customer
            started.
        status:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/IntentStatus'
              description: '`null` while the processor has not answered.'
    ReminderSettings:
      oneOf:
        - type: object
          title: Snapshot
          description: The settings that finalise froze. The reminders run on them.
          required:
            - reminders_enabled
            - offsets_minutes
            - paused
            - kind
          properties:
            kind:
              type: string
              enum:
                - snapshot
              x-stainless-const: true
            offsets_minutes:
              type: array
              items:
                type: integer
                format: int64
            paused:
              type: boolean
            reminders_enabled:
              type: boolean
        - type: object
          title: Override
          description: >-
            The changes of a draft. A `null` field keeps the business value at
            finalise.
          required:
            - kind
          properties:
            kind:
              type: string
              enum:
                - override
              x-stainless-const: true
            offsets_minutes:
              type:
                - array
                - 'null'
              items:
                type: integer
                format: int64
            paused:
              type:
                - boolean
                - 'null'
            reminders_enabled:
              type:
                - boolean
                - 'null'
      description: >-
        The stored reminder settings of the invoice. Offsets are minutes from
        the due date.
      discriminator:
        propertyName: kind
    InvoiceStatus:
      type: string
      description: The `message` of each variant is the label of the invoice document.
      enum:
        - open
        - paid
        - void
        - draft
        - past_due
        - uncollectable
    InvoiceTag:
      type: string
      enum:
        - refunded
        - partially_refunded
        - disputed
        - payment_reversed
    InvoiceBillingAddress:
      type: object
      description: A draft can have no country yet. Finalise needs it.
      properties:
        city:
          type:
            - string
            - 'null'
        country:
          oneOf:
            - type: 'null'
            - $ref: '#/components/schemas/CountryCodeAlpha2'
        state:
          type:
            - string
            - 'null'
        street:
          type:
            - string
            - 'null'
        zipcode:
          type:
            - string
            - 'null'
    TimeInterval:
      type: string
      description: Unit of a duration count (e.g. license-key validity period).
      enum:
        - Day
        - Week
        - Month
        - Year
    LineKind:
      type: string
      enum:
        - subscription
        - addon
        - meter
        - credit_overage
        - one_time
    IntentStatus:
      type: string
      enum:
        - succeeded
        - failed
        - cancelled
        - processing
        - requires_customer_action
        - requires_merchant_action
        - requires_payment_method
        - requires_confirmation
        - requires_capture
        - partially_captured
        - partially_captured_and_capturable
    CountryCodeAlpha2:
      type: string
      description: ISO country code alpha2 variant
      enum:
        - AF
        - AX
        - AL
        - DZ
        - AS
        - AD
        - AO
        - AI
        - AQ
        - AG
        - AR
        - AM
        - AW
        - AU
        - AT
        - AZ
        - BS
        - BH
        - BD
        - BB
        - BY
        - BE
        - BZ
        - BJ
        - BM
        - BT
        - BO
        - BQ
        - BA
        - BW
        - BV
        - BR
        - IO
        - BN
        - BG
        - BF
        - BI
        - KH
        - CM
        - CA
        - CV
        - KY
        - CF
        - TD
        - CL
        - CN
        - CX
        - CC
        - CO
        - KM
        - CG
        - CD
        - CK
        - CR
        - CI
        - HR
        - CU
        - CW
        - CY
        - CZ
        - DK
        - DJ
        - DM
        - DO
        - EC
        - EG
        - SV
        - GQ
        - ER
        - EE
        - ET
        - FK
        - FO
        - FJ
        - FI
        - FR
        - GF
        - PF
        - TF
        - GA
        - GM
        - GE
        - DE
        - GH
        - GI
        - GR
        - GL
        - GD
        - GP
        - GU
        - GT
        - GG
        - GN
        - GW
        - GY
        - HT
        - HM
        - VA
        - HN
        - HK
        - HU
        - IS
        - IN
        - ID
        - IR
        - IQ
        - IE
        - IM
        - IL
        - IT
        - JM
        - JP
        - JE
        - JO
        - KZ
        - KE
        - KI
        - KP
        - KR
        - KW
        - KG
        - LA
        - LV
        - LB
        - LS
        - LR
        - LY
        - LI
        - LT
        - LU
        - MO
        - MK
        - MG
        - MW
        - MY
        - MV
        - ML
        - MT
        - MH
        - MQ
        - MR
        - MU
        - YT
        - MX
        - FM
        - MD
        - MC
        - MN
        - ME
        - MS
        - MA
        - MZ
        - MM
        - NA
        - NR
        - NP
        - NL
        - NC
        - NZ
        - NI
        - NE
        - NG
        - NU
        - NF
        - MP
        - 'NO'
        - OM
        - PK
        - PW
        - PS
        - PA
        - PG
        - PY
        - PE
        - PH
        - PN
        - PL
        - PT
        - PR
        - QA
        - RE
        - RO
        - RU
        - RW
        - BL
        - SH
        - KN
        - LC
        - MF
        - PM
        - VC
        - WS
        - SM
        - ST
        - SA
        - SN
        - RS
        - SC
        - SL
        - SG
        - SX
        - SK
        - SI
        - SB
        - SO
        - ZA
        - GS
        - SS
        - ES
        - LK
        - SD
        - SR
        - SJ
        - SZ
        - SE
        - CH
        - SY
        - TW
        - TJ
        - TZ
        - TH
        - TL
        - TG
        - TK
        - TO
        - TT
        - TN
        - TR
        - TM
        - TC
        - TV
        - UG
        - UA
        - AE
        - GB
        - UM
        - US
        - UY
        - UZ
        - VU
        - VE
        - VN
        - VG
        - VI
        - WF
        - EH
        - YE
        - ZM
        - ZW
  securitySchemes:
    API_KEY:
      type: http
      scheme: bearer
      description: >-
        Send your API key as a bearer token: `Authorization: Bearer <api_key>`.
        A test mode key starts with `dodo_test_`, for example
        `dodo_test_AbCd1234EfGh5678.<secret>`. A live mode key starts with
        `dodo_live_`. Use a test mode key on `test.dodopayments.com` and a live
        mode key on `live.dodopayments.com`. Keys from before these tags have no
        tag and operate as before.

````

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