Stripe API for OpenResty

$ opm get gnois/lua-resty-stripe


Stripe API for OpenResty


    opm add gnois\lua-resty-stripe


    local rhttp = require("resty.http")
    local stripe = require("resty.stripe")
    local ApiKey = "..."  -- your stripe api key
    local api = stripe(, ApiKey))
    local status, headers_or_err, subs = api.subscriptions.get(subscription_id)
    if status < 300 then
       -- process subscription...


The list of API closely follows the REST Endpoint in Stripe Reference.

For creation and modification API (HTTP POST endpoints), we can supply an Idempotency-Key HTTP header as the last parameter which will enable 3 retries if there is error and Stripe-Should-Retry header is set to true, as documented in Low level error handling.


The Stripe webhook guide documents the steps to handle Stripe notification to your application.

Assuming we are using Losty, here is how we would create a webhook endpoint in our application to receive these notifications.

    local web = require('losty.web')()   -- instantiate once
    local body = require('losty.body')
    local content = require('losty.content')
    local wh = require('stripe_webhook')
    local WebhookSecret = ""
    local w = web.route()'/stripe-webhook', content.json, function(q, r)
       local raw = body.raw(q)
       local event, err =, q.headers['stripe-signature'], WebhookSecret)
       if not event then
          ngx.log(ngx.ERR, err)
          r.status = 400
          local obj =
          if 'customer.created' == event.type then
             local uid = obj.metadata['']
             if uid then
                -- link user id to stripe customer id in database ...
                r.status = 200
                r.status = 400
                return {fail = "invalid metadata"}

Adding more APIs

The list of API are not comprehensive for now, as I am only adding the ones that I need. Pull requests are always welcomed.

Adding new APIs from the Stripe Reference is very easy, although it is using (Luaty)[].

For example, looking at the reference for SetupIntents, we can see that there are Create, Retrieve, Update, Confirm, Cancel and List all operations. The Endpoints given for these operations can be directly translated into code as below:

    var SetupIntents = "setup_intents"
    K.setup_intents = {
       get = \id, opt -> return get(SetupIntents, id, opt)
       , create = \... -> return create(SetupIntents, ...)
       , update = \id, ... -> return post(SetupIntents, id, ...)
       , confirm = \id, ... -> return post(SetupIntents, id .. "/confirm", ...)
       , cancel = \id, ... -> return post(SetupIntents, id .. "/cancel", ...)
       , list = \opt -> return list(SetupIntents, opt)

There are a few patterns to note though:

  • Stripe REST endpoints are using only HTTP verbs GET and POST

  • HTTP GET is normally used to list all items or get one item, which should require an ID.

  • HTTP POST is used to either create a new item or post changes to an item, which should require an ID, and sometimes followed by the operation name, for eg confirm or cancel as seen above. create and post functions are taking varargs because a HTTP header with an idempotency key can be passed in.