0

Create Webhook Endpoint

by
Published Oct 30, 2023

Register a URL (e.g. a Windmill HTTP route) to receive events. `enabled_events` lists event types such as `invoice.paid`, or `*` for all. The response's `secret` (`whsec_...`) verifies the Stripe-Signature header and is only returned here. Without `api_version`, payloads use the account's default API version.

Script stripe Verified

The script

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

3
/**
4
 * Create Webhook Endpoint
5
 * Register a URL (e.g. a Windmill HTTP route) to receive events. `enabled_events` lists event types such as `invoice.paid`, or `*` for all. The response's `secret` (`whsec_...`) verifies the Stripe-Signature header and is only returned here. Without `api_version`, payloads use the account's default API version.
6
 */
7
export async function main(
8
  auth: RT.Stripe,
9
  url: string,
10
  enabled_events: string[],
11
  description: string | undefined,
12
  api_version: string | undefined,
13
  metadata: { [key: string]: string } | undefined
14
) {
15
  const response = await fetch(`https://api.stripe.com/v1/webhook_endpoints`, {
16
    method: "POST",
17
    headers: {
18
      Authorization: `Bearer ${auth.token}`,
19
      "Content-Type": "application/x-www-form-urlencoded",
20
      Accept: "application/json",
21
      "Stripe-Version": "2025-03-31.basil",
22
    },
23
    body: toForm({ url, enabled_events, description, api_version, metadata }),
24
  })
25

26
  if (!response.ok) {
27
    throw new Error(`${response.status} ${await response.text()}`)
28
  }
29

30
  return await response.json()
31
}
32

33
// Stripe takes form-encoded params with bracketed nesting: metadata[key]=v, items[0][price]=p
34
function toForm(
35
  params: { [key: string]: any },
36
  prefix = "",
37
  out = new URLSearchParams()
38
) {
39
  for (const [key, value] of Object.entries(params)) {
40
    if (value == null || value === "") continue
41
    const name = prefix ? `${prefix}[${key}]` : key
42
    if (typeof value === "object") toForm(value, name, out)
43
    else out.append(name, String(value))
44
  }
45
  return out
46
}
47

Other submissions
  • Submitted by hugo697 Typescript (fetch-only)
    Created 528 days ago
    1
    type Stripe = {
    2
      token: string;
    3
    };
    4
    /**
    5
     * Post webhook endpoints
    6
     * A webhook endpoint must have a url and a list of enabled_events. You may optionally specify the Boolean connect parameter. If set to true, then a Connect webhook endpoint that notifies the specified url about events from all connected accounts is created; otherwise an account webhook endpoint that notifies the specified url only about events from your account is created. You can also create webhook endpoints in the webhooks settings section of the Dashboard.
    7
     */
    8
    export async function main(
    9
      auth: Stripe,
    10
      body: {
    11
        api_version?:
    12
          | "2011-01-01"
    13
          | "2011-06-21"
    14
          | "2011-06-28"
    15
          | "2011-08-01"
    16
          | "2011-09-15"
    17
          | "2011-11-17"
    18
          | "2012-02-23"
    19
          | "2012-03-25"
    20
          | "2012-06-18"
    21
          | "2012-06-28"
    22
          | "2012-07-09"
    23
          | "2012-09-24"
    24
          | "2012-10-26"
    25
          | "2012-11-07"
    26
          | "2013-02-11"
    27
          | "2013-02-13"
    28
          | "2013-07-05"
    29
          | "2013-08-12"
    30
          | "2013-08-13"
    31
          | "2013-10-29"
    32
          | "2013-12-03"
    33
          | "2014-01-31"
    34
          | "2014-03-13"
    35
          | "2014-03-28"
    36
          | "2014-05-19"
    37
          | "2014-06-13"
    38
          | "2014-06-17"
    39
          | "2014-07-22"
    40
          | "2014-07-26"
    41
          | "2014-08-04"
    42
          | "2014-08-20"
    43
          | "2014-09-08"
    44
          | "2014-10-07"
    45
          | "2014-11-05"
    46
          | "2014-11-20"
    47
          | "2014-12-08"
    48
          | "2014-12-17"
    49
          | "2014-12-22"
    50
          | "2015-01-11"
    51
          | "2015-01-26"
    52
          | "2015-02-10"
    53
          | "2015-02-16"
    54
          | "2015-02-18"
    55
          | "2015-03-24"
    56
          | "2015-04-07"
    57
          | "2015-06-15"
    58
          | "2015-07-07"
    59
          | "2015-07-13"
    60
          | "2015-07-28"
    61
          | "2015-08-07"
    62
          | "2015-08-19"
    63
          | "2015-09-03"
    64
          | "2015-09-08"
    65
          | "2015-09-23"
    66
          | "2015-10-01"
    67
          | "2015-10-12"
    68
          | "2015-10-16"
    69
          | "2016-02-03"
    70
          | "2016-02-19"
    71
          | "2016-02-22"
    72
          | "2016-02-23"
    73
          | "2016-02-29"
    74
          | "2016-03-07"
    75
          | "2016-06-15"
    76
          | "2016-07-06"
    77
          | "2016-10-19"
    78
          | "2017-01-27"
    79
          | "2017-02-14"
    80
          | "2017-04-06"
    81
          | "2017-05-25"
    82
          | "2017-06-05"
    83
          | "2017-08-15"
    84
          | "2017-12-14"
    85
          | "2018-01-23"
    86
          | "2018-02-05"
    87
          | "2018-02-06"
    88
          | "2018-02-28"
    89
          | "2018-05-21"
    90
          | "2018-07-27"
    91
          | "2018-08-23"
    92
          | "2018-09-06"
    93
          | "2018-09-24"
    94
          | "2018-10-31"
    95
          | "2018-11-08"
    96
          | "2019-02-11"
    97
          | "2019-02-19"
    98
          | "2019-03-14"
    99
          | "2019-05-16"
    100
          | "2019-08-14"
    101
          | "2019-09-09"
    102
          | "2019-10-08"
    103
          | "2019-10-17"
    104
          | "2019-11-05"
    105
          | "2019-12-03"
    106
          | "2020-03-02"
    107
          | "2020-08-27"
    108
          | "2022-08-01"
    109
          | "2022-11-15"
    110
          | "2023-08-16"
    111
          | "2023-10-16";
    112
        connect?: boolean;
    113
        description?: string | "";
    114
        enabled_events: (
    115
          | "*"
    116
          | "account.application.authorized"
    117
          | "account.application.deauthorized"
    118
          | "account.external_account.created"
    119
          | "account.external_account.deleted"
    120
          | "account.external_account.updated"
    121
          | "account.updated"
    122
          | "application_fee.created"
    123
          | "application_fee.refund.updated"
    124
          | "application_fee.refunded"
    125
          | "balance.available"
    126
          | "billing_portal.configuration.created"
    127
          | "billing_portal.configuration.updated"
    128
          | "billing_portal.session.created"
    129
          | "capability.updated"
    130
          | "cash_balance.funds_available"
    131
          | "charge.captured"
    132
          | "charge.dispute.closed"
    133
          | "charge.dispute.created"
    134
          | "charge.dispute.funds_reinstated"
    135
          | "charge.dispute.funds_withdrawn"
    136
          | "charge.dispute.updated"
    137
          | "charge.expired"
    138
          | "charge.failed"
    139
          | "charge.pending"
    140
          | "charge.refund.updated"
    141
          | "charge.refunded"
    142
          | "charge.succeeded"
    143
          | "charge.updated"
    144
          | "checkout.session.async_payment_failed"
    145
          | "checkout.session.async_payment_succeeded"
    146
          | "checkout.session.completed"
    147
          | "checkout.session.expired"
    148
          | "climate.order.canceled"
    149
          | "climate.order.created"
    150
          | "climate.order.delayed"
    151
          | "climate.order.delivered"
    152
          | "climate.order.product_substituted"
    153
          | "climate.product.created"
    154
          | "climate.product.pricing_updated"
    155
          | "coupon.created"
    156
          | "coupon.deleted"
    157
          | "coupon.updated"
    158
          | "credit_note.created"
    159
          | "credit_note.updated"
    160
          | "credit_note.voided"
    161
          | "customer.created"
    162
          | "customer.deleted"
    163
          | "customer.discount.created"
    164
          | "customer.discount.deleted"
    165
          | "customer.discount.updated"
    166
          | "customer.source.created"
    167
          | "customer.source.deleted"
    168
          | "customer.source.expiring"
    169
          | "customer.source.updated"
    170
          | "customer.subscription.created"
    171
          | "customer.subscription.deleted"
    172
          | "customer.subscription.paused"
    173
          | "customer.subscription.pending_update_applied"
    174
          | "customer.subscription.pending_update_expired"
    175
          | "customer.subscription.resumed"
    176
          | "customer.subscription.trial_will_end"
    177
          | "customer.subscription.updated"
    178
          | "customer.tax_id.created"
    179
          | "customer.tax_id.deleted"
    180
          | "customer.tax_id.updated"
    181
          | "customer.updated"
    182
          | "customer_cash_balance_transaction.created"
    183
          | "file.created"
    184
          | "financial_connections.account.created"
    185
          | "financial_connections.account.deactivated"
    186
          | "financial_connections.account.disconnected"
    187
          | "financial_connections.account.reactivated"
    188
          | "financial_connections.account.refreshed_balance"
    189
          | "financial_connections.account.refreshed_ownership"
    190
          | "financial_connections.account.refreshed_transactions"
    191
          | "identity.verification_session.canceled"
    192
          | "identity.verification_session.created"
    193
          | "identity.verification_session.processing"
    194
          | "identity.verification_session.redacted"
    195
          | "identity.verification_session.requires_input"
    196
          | "identity.verification_session.verified"
    197
          | "invoice.created"
    198
          | "invoice.deleted"
    199
          | "invoice.finalization_failed"
    200
          | "invoice.finalized"
    201
          | "invoice.marked_uncollectible"
    202
          | "invoice.paid"
    203
          | "invoice.payment_action_required"
    204
          | "invoice.payment_failed"
    205
          | "invoice.payment_succeeded"
    206
          | "invoice.sent"
    207
          | "invoice.upcoming"
    208
          | "invoice.updated"
    209
          | "invoice.voided"
    210
          | "invoiceitem.created"
    211
          | "invoiceitem.deleted"
    212
          | "issuing_authorization.created"
    213
          | "issuing_authorization.request"
    214
          | "issuing_authorization.updated"
    215
          | "issuing_card.created"
    216
          | "issuing_card.updated"
    217
          | "issuing_cardholder.created"
    218
          | "issuing_cardholder.updated"
    219
          | "issuing_dispute.closed"
    220
          | "issuing_dispute.created"
    221
          | "issuing_dispute.funds_reinstated"
    222
          | "issuing_dispute.submitted"
    223
          | "issuing_dispute.updated"
    224
          | "issuing_token.created"
    225
          | "issuing_token.updated"
    226
          | "issuing_transaction.created"
    227
          | "issuing_transaction.updated"
    228
          | "mandate.updated"
    229
          | "payment_intent.amount_capturable_updated"
    230
          | "payment_intent.canceled"
    231
          | "payment_intent.created"
    232
          | "payment_intent.partially_funded"
    233
          | "payment_intent.payment_failed"
    234
          | "payment_intent.processing"
    235
          | "payment_intent.requires_action"
    236
          | "payment_intent.succeeded"
    237
          | "payment_link.created"
    238
          | "payment_link.updated"
    239
          | "payment_method.attached"
    240
          | "payment_method.automatically_updated"
    241
          | "payment_method.detached"
    242
          | "payment_method.updated"
    243
          | "payout.canceled"
    244
          | "payout.created"
    245
          | "payout.failed"
    246
          | "payout.paid"
    247
          | "payout.reconciliation_completed"
    248
          | "payout.updated"
    249
          | "person.created"
    250
          | "person.deleted"
    251
          | "person.updated"
    252
          | "plan.created"
    253
          | "plan.deleted"
    254
          | "plan.updated"
    255
          | "price.created"
    256
          | "price.deleted"
    257
          | "price.updated"
    258
          | "product.created"
    259
          | "product.deleted"
    260
          | "product.updated"
    261
          | "promotion_code.created"
    262
          | "promotion_code.updated"
    263
          | "quote.accepted"
    264
          | "quote.canceled"
    265
          | "quote.created"
    266
          | "quote.finalized"
    267
          | "radar.early_fraud_warning.created"
    268
          | "radar.early_fraud_warning.updated"
    269
          | "refund.created"
    270
          | "refund.updated"
    271
          | "reporting.report_run.failed"
    272
          | "reporting.report_run.succeeded"
    273
          | "reporting.report_type.updated"
    274
          | "review.closed"
    275
          | "review.opened"
    276
          | "setup_intent.canceled"
    277
          | "setup_intent.created"
    278
          | "setup_intent.requires_action"
    279
          | "setup_intent.setup_failed"
    280
          | "setup_intent.succeeded"
    281
          | "sigma.scheduled_query_run.created"
    282
          | "source.canceled"
    283
          | "source.chargeable"
    284
          | "source.failed"
    285
          | "source.mandate_notification"
    286
          | "source.refund_attributes_required"
    287
          | "source.transaction.created"
    288
          | "source.transaction.updated"
    289
          | "subscription_schedule.aborted"
    290
          | "subscription_schedule.canceled"
    291
          | "subscription_schedule.completed"
    292
          | "subscription_schedule.created"
    293
          | "subscription_schedule.expiring"
    294
          | "subscription_schedule.released"
    295
          | "subscription_schedule.updated"
    296
          | "tax.settings.updated"
    297
          | "tax_rate.created"
    298
          | "tax_rate.updated"
    299
          | "terminal.reader.action_failed"
    300
          | "terminal.reader.action_succeeded"
    301
          | "test_helpers.test_clock.advancing"
    302
          | "test_helpers.test_clock.created"
    303
          | "test_helpers.test_clock.deleted"
    304
          | "test_helpers.test_clock.internal_failure"
    305
          | "test_helpers.test_clock.ready"
    306
          | "topup.canceled"
    307
          | "topup.created"
    308
          | "topup.failed"
    309
          | "topup.reversed"
    310
          | "topup.succeeded"
    311
          | "transfer.created"
    312
          | "transfer.reversed"
    313
          | "transfer.updated"
    314
          | "treasury.credit_reversal.created"
    315
          | "treasury.credit_reversal.posted"
    316
          | "treasury.debit_reversal.completed"
    317
          | "treasury.debit_reversal.created"
    318
          | "treasury.debit_reversal.initial_credit_granted"
    319
          | "treasury.financial_account.closed"
    320
          | "treasury.financial_account.created"
    321
          | "treasury.financial_account.features_status_updated"
    322
          | "treasury.inbound_transfer.canceled"
    323
          | "treasury.inbound_transfer.created"
    324
          | "treasury.inbound_transfer.failed"
    325
          | "treasury.inbound_transfer.succeeded"
    326
          | "treasury.outbound_payment.canceled"
    327
          | "treasury.outbound_payment.created"
    328
          | "treasury.outbound_payment.expected_arrival_date_updated"
    329
          | "treasury.outbound_payment.failed"
    330
          | "treasury.outbound_payment.posted"
    331
          | "treasury.outbound_payment.returned"
    332
          | "treasury.outbound_transfer.canceled"
    333
          | "treasury.outbound_transfer.created"
    334
          | "treasury.outbound_transfer.expected_arrival_date_updated"
    335
          | "treasury.outbound_transfer.failed"
    336
          | "treasury.outbound_transfer.posted"
    337
          | "treasury.outbound_transfer.returned"
    338
          | "treasury.received_credit.created"
    339
          | "treasury.received_credit.failed"
    340
          | "treasury.received_credit.succeeded"
    341
          | "treasury.received_debit.created"
    342
        )[];
    343
        expand?: string[];
    344
        metadata?: { [k: string]: string } | "";
    345
        url: string;
    346
      }
    347
    ) {
    348
      const url = new URL(`https://api.stripe.com/v1/webhook_endpoints`);
    349
    
    
    350
      const response = await fetch(url, {
    351
        method: "POST",
    352
        headers: {
    353
          "Content-Type": "application/x-www-form-urlencoded",
    354
          Authorization: "Bearer " + auth.token,
    355
        },
    356
        body: encodeParams(body),
    357
      });
    358
      if (!response.ok) {
    359
        const text = await response.text();
    360
        throw new Error(`${response.status} ${text}`);
    361
      }
    362
      return await response.json();
    363
    }
    364
    
    
    365
    function encodeParams(o: any) {
    366
      function iter(o: any, path: string) {
    367
        if (Array.isArray(o)) {
    368
          o.forEach(function (a) {
    369
            iter(a, path + "[]");
    370
          });
    371
          return;
    372
        }
    373
        if (o !== null && typeof o === "object") {
    374
          Object.keys(o).forEach(function (k) {
    375
            iter(o[k], path + "[" + k + "]");
    376
          });
    377
          return;
    378
        }
    379
        data.push(path + "=" + o);
    380
      }
    381
      const data: string[] = [];
    382
      Object.keys(o).forEach(function (k) {
    383
        if (o[k] !== undefined) {
    384
          iter(o[k], k);
    385
        }
    386
      });
    387
      return new URLSearchParams(data.join("&"));
    388
    }
    389