0

Update Invoice

by
Published Oct 30, 2023

Update a draft invoice. Once finalized, only a few fields (description, metadata, footer...) remain editable. Empty fields are left unchanged. `extra_params` passes any other documented field through as-is.

Script stripe Verified

The script

Submitted by hugo989 Typescript (fetch-only)
Verified 2 hours ago
1
//native
2

3
/**
4
 * Update Invoice
5
 * Update a draft invoice. Once finalized, only a few fields (description, metadata, footer...) remain editable. Empty fields are left unchanged. `extra_params` passes any other documented field through as-is.
6
 */
7
export async function main(
8
  auth: RT.Stripe,
9
  invoice_id: string,
10
  description: string | undefined,
11
  collection_method: "charge_automatically" | "send_invoice" | undefined,
12
  days_until_due: number | undefined,
13
  default_payment_method: string | undefined,
14
  metadata: { [key: string]: string } | undefined,
15
  extra_params: { [key: string]: any } | undefined
16
) {
17
  const response = await fetch(
18
    `https://api.stripe.com/v1/invoices/${invoice_id}`,
19
    {
20
      method: "POST",
21
      headers: {
22
        Authorization: `Bearer ${auth.token}`,
23
        "Content-Type": "application/x-www-form-urlencoded",
24
        Accept: "application/json",
25
        "Stripe-Version": "2025-03-31.basil",
26
      },
27
      body: toForm({
28
        description,
29
        collection_method,
30
        days_until_due,
31
        default_payment_method,
32
        metadata,
33
        ...extra_params,
34
      }),
35
    }
36
  )
37

38
  if (!response.ok) {
39
    throw new Error(`${response.status} ${await response.text()}`)
40
  }
41

42
  return await response.json()
43
}
44

45
// Stripe takes form-encoded params with bracketed nesting: metadata[key]=v, items[0][price]=p
46
function toForm(
47
  params: { [key: string]: any },
48
  prefix = "",
49
  out = new URLSearchParams()
50
) {
51
  for (const [key, value] of Object.entries(params)) {
52
    if (value == null || value === "") continue
53
    const name = prefix ? `${prefix}[${key}]` : key
54
    if (typeof value === "object") toForm(value, name, out)
55
    else out.append(name, String(value))
56
  }
57
  return out
58
}
59

Other submissions
  • Submitted by hugo697 Typescript (fetch-only)
    Created 528 days ago
    1
    type Stripe = {
    2
      token: string;
    3
    };
    4
    /**
    5
     * Post invoices invoice
    6
     * Draft invoices are fully editable. Once an invoice is finalized,
    7
    monetary values, as well as collection_method, become uneditable.
    8
    
    
    9
    If you would like to stop the Stripe Billing engine from automatically finalizing, reattempting payments on,
    10
    sending reminders for, or automatically reconciling invoices, pass
    11
    auto_advance=false.
    12
     */
    13
    export async function main(
    14
      auth: Stripe,
    15
      invoice: string,
    16
      body: {
    17
        account_tax_ids?: string[] | "";
    18
        application_fee_amount?: number;
    19
        auto_advance?: boolean;
    20
        automatic_tax?: {
    21
          enabled: boolean;
    22
          liability?: {
    23
            account?: string;
    24
            type: "account" | "self";
    25
            [k: string]: unknown;
    26
          };
    27
          [k: string]: unknown;
    28
        };
    29
        collection_method?: "charge_automatically" | "send_invoice";
    30
        custom_fields?:
    31
          | { name: string; value: string; [k: string]: unknown }[]
    32
          | "";
    33
        days_until_due?: number;
    34
        default_payment_method?: string;
    35
        default_source?: string | "";
    36
        default_tax_rates?: string[] | "";
    37
        description?: string;
    38
        discounts?:
    39
          | { coupon?: string; discount?: string; [k: string]: unknown }[]
    40
          | "";
    41
        due_date?: number;
    42
        effective_at?: number | "";
    43
        expand?: string[];
    44
        footer?: string;
    45
        issuer?: {
    46
          account?: string;
    47
          type: "account" | "self";
    48
          [k: string]: unknown;
    49
        };
    50
        metadata?: { [k: string]: string } | "";
    51
        number?: string | "";
    52
        on_behalf_of?: string | "";
    53
        payment_settings?: {
    54
          default_mandate?: string | "";
    55
          payment_method_options?: {
    56
            acss_debit?:
    57
              | {
    58
                  mandate_options?: {
    59
                    transaction_type?: "business" | "personal";
    60
                    [k: string]: unknown;
    61
                  };
    62
                  verification_method?: "automatic" | "instant" | "microdeposits";
    63
                  [k: string]: unknown;
    64
                }
    65
              | "";
    66
            bancontact?:
    67
              | {
    68
                  preferred_language?: "de" | "en" | "fr" | "nl";
    69
                  [k: string]: unknown;
    70
                }
    71
              | "";
    72
            card?:
    73
              | {
    74
                  installments?: {
    75
                    enabled?: boolean;
    76
                    plan?:
    77
                      | {
    78
                          count: number;
    79
                          interval: "month";
    80
                          type: "fixed_count";
    81
                          [k: string]: unknown;
    82
                        }
    83
                      | "";
    84
                    [k: string]: unknown;
    85
                  };
    86
                  request_three_d_secure?: "any" | "automatic" | "challenge";
    87
                  [k: string]: unknown;
    88
                }
    89
              | "";
    90
            customer_balance?:
    91
              | {
    92
                  bank_transfer?: {
    93
                    eu_bank_transfer?: { country: string; [k: string]: unknown };
    94
                    type?: string;
    95
                    [k: string]: unknown;
    96
                  };
    97
                  funding_type?: string;
    98
                  [k: string]: unknown;
    99
                }
    100
              | "";
    101
            konbini?: { [k: string]: unknown } | "";
    102
            us_bank_account?:
    103
              | {
    104
                  financial_connections?: {
    105
                    permissions?: (
    106
                      | "balances"
    107
                      | "ownership"
    108
                      | "payment_method"
    109
                      | "transactions"
    110
                    )[];
    111
                    prefetch?: ("balances" | "transactions")[];
    112
                    [k: string]: unknown;
    113
                  };
    114
                  verification_method?: "automatic" | "instant" | "microdeposits";
    115
                  [k: string]: unknown;
    116
                }
    117
              | "";
    118
            [k: string]: unknown;
    119
          };
    120
          payment_method_types?:
    121
            | (
    122
                | "ach_credit_transfer"
    123
                | "ach_debit"
    124
                | "acss_debit"
    125
                | "au_becs_debit"
    126
                | "bacs_debit"
    127
                | "bancontact"
    128
                | "boleto"
    129
                | "card"
    130
                | "cashapp"
    131
                | "customer_balance"
    132
                | "eps"
    133
                | "fpx"
    134
                | "giropay"
    135
                | "grabpay"
    136
                | "ideal"
    137
                | "konbini"
    138
                | "link"
    139
                | "p24"
    140
                | "paynow"
    141
                | "paypal"
    142
                | "promptpay"
    143
                | "sepa_debit"
    144
                | "sofort"
    145
                | "us_bank_account"
    146
                | "wechat_pay"
    147
              )[]
    148
            | "";
    149
          [k: string]: unknown;
    150
        };
    151
        rendering?: {
    152
          amount_tax_display?: "" | "exclude_tax" | "include_inclusive_tax";
    153
          pdf?: { page_size?: "a4" | "auto" | "letter"; [k: string]: unknown };
    154
          [k: string]: unknown;
    155
        };
    156
        shipping_cost?:
    157
          | {
    158
              shipping_rate?: string;
    159
              shipping_rate_data?: {
    160
                delivery_estimate?: {
    161
                  maximum?: {
    162
                    unit: "business_day" | "day" | "hour" | "month" | "week";
    163
                    value: number;
    164
                    [k: string]: unknown;
    165
                  };
    166
                  minimum?: {
    167
                    unit: "business_day" | "day" | "hour" | "month" | "week";
    168
                    value: number;
    169
                    [k: string]: unknown;
    170
                  };
    171
                  [k: string]: unknown;
    172
                };
    173
                display_name: string;
    174
                fixed_amount?: {
    175
                  amount: number;
    176
                  currency: string;
    177
                  currency_options?: {
    178
                    [k: string]: {
    179
                      amount: number;
    180
                      tax_behavior?: "exclusive" | "inclusive" | "unspecified";
    181
                      [k: string]: unknown;
    182
                    };
    183
                  };
    184
                  [k: string]: unknown;
    185
                };
    186
                metadata?: { [k: string]: string };
    187
                tax_behavior?: "exclusive" | "inclusive" | "unspecified";
    188
                tax_code?: string;
    189
                type?: "fixed_amount";
    190
                [k: string]: unknown;
    191
              };
    192
              [k: string]: unknown;
    193
            }
    194
          | "";
    195
        shipping_details?:
    196
          | {
    197
              address: {
    198
                city?: string;
    199
                country?: string;
    200
                line1?: string;
    201
                line2?: string;
    202
                postal_code?: string;
    203
                state?: string;
    204
                [k: string]: unknown;
    205
              };
    206
              name: string;
    207
              phone?: string | "";
    208
              [k: string]: unknown;
    209
            }
    210
          | "";
    211
        statement_descriptor?: string;
    212
        transfer_data?:
    213
          | { amount?: number; destination: string; [k: string]: unknown }
    214
          | "";
    215
      }
    216
    ) {
    217
      const url = new URL(`https://api.stripe.com/v1/invoices/${invoice}`);
    218
    
    
    219
      const response = await fetch(url, {
    220
        method: "POST",
    221
        headers: {
    222
          "Content-Type": "application/x-www-form-urlencoded",
    223
          Authorization: "Bearer " + auth.token,
    224
        },
    225
        body: encodeParams(body),
    226
      });
    227
      if (!response.ok) {
    228
        const text = await response.text();
    229
        throw new Error(`${response.status} ${text}`);
    230
      }
    231
      return await response.json();
    232
    }
    233
    
    
    234
    function encodeParams(o: any) {
    235
      function iter(o: any, path: string) {
    236
        if (Array.isArray(o)) {
    237
          o.forEach(function (a) {
    238
            iter(a, path + "[]");
    239
          });
    240
          return;
    241
        }
    242
        if (o !== null && typeof o === "object") {
    243
          Object.keys(o).forEach(function (k) {
    244
            iter(o[k], path + "[" + k + "]");
    245
          });
    246
          return;
    247
        }
    248
        data.push(path + "=" + o);
    249
      }
    250
      const data: string[] = [];
    251
      Object.keys(o).forEach(function (k) {
    252
        if (o[k] !== undefined) {
    253
          iter(o[k], k);
    254
        }
    255
      });
    256
      return new URLSearchParams(data.join("&"));
    257
    }
    258