←back to thread

194 points strnisa | 3 comments | | HN request time: 0.002s | source

Hi HN,

I built Small Transfers, a payments platform for SaaS / API makers who want to bill customers per request instead of pushing them into subscriptions or pre-buy packages.

*Why?*

  - Many customers hate subscriptions and/or want to use a service occasionally.
  - Traditional payment processors add a fixed fee to every charge, making charges below 1 USD impractical.
  - Stripe UBB tracks usage, but you still need to write your own auth, add spending limits, and each merchant charges cards separately (extra fees for customers).
*How it works?*

  - Each merchant has a Small Transfers account linked to their Stripe account via Stripe Connect, which is used to transfer payouts to merchants.
  - Each customer has a Small Transfers account where we verify them using Google Sign-In, 3-D Secure, and Stripe Radar to minimise the chances of a customer not paying their balance.
  - Customers allow your service to identify and charge them via platform's own OAuth. This also removes the need for your service to implement its own auth. (Simple services don't even need their own database.)
  - Merchants call a simple REST API to authorize and capture a charge with a minimum amount of 0.000001 USD. Note that you can authorize more than you capture, allowing you to authorize the max amount your request might use, and then capture your actual cost plus margin (great for many use cases, e.g., AI).
  - The platform takes care of charging customers and sending payouts to merchants.
  - Merchants pay a flat 3% fee. Customers pay payment processing fees when they pay for their balance.
There's a Next.js Starter project (https://github.com/smalltransfers/nextjs-starter) and a live demo (https://nextjs-starter.smalltransfers.com/).

I've been dog-fooding the platform with my own service (https://unattach.com/) and would love your feedback, specifically:

  - The general approach and whether there is anything I should do differently.
  - Any concerns and how I could mitigate them.
  - Any other feedback.
I'm also looking for more merchants to try out the platform, and can help you with the integration.

Thank you for your time! Happy to answer questions here.

Show context
Roguelazer ◴[] No.45216996[source]
Some API questions/observations

- I don't see an idempotency key in the request to authorize a charge; that might be something nice for people looking to build reliable systems on this. - How long are accessTokens valid? Forever? Do they become invalid if the subject metadata (firstName, lastName, email) changes?

I think this is a super-cool idea, but I think the idea of extending net30 terms to every customer of some B2C product seems pretty iffy; since you're deferring charging until the end of the month, you won't get most of the fraud signals from Stripe until then and anything popular that used this system seems like it'd be pretty inundated with fraud. I would at least consider doing the charges more frequently (i.e., charge at the end of the month or every $50, whichever comes first) to put a better bound on how long you can go before finding out that someone gave you a stolen card.

replies(3): >>45218416 #>>45219763 #>>45221312 #
strnisa ◴[] No.45219763[source]
We run Stripe Radar and 3-D Secure when adding a card (before first use), which filters out a lot of obvious fraud (and 3DS often shifts liability to card networks in many regions).

The balances are not settled just at the end of the month. Each customer has a "maximum owed limit", which starts low (currently 10 USD) and grows with successful payments (up to 30 USD currently). The customer is charged as soon as they hit that limit (with some grace to allow for continued use).

Idempotency keys are on the near-term roadmap. Access tokens do not currently expire; however, they can be revoked by the customer at any time.

replies(1): >>45235867 #
franga2000 ◴[] No.45235867[source]
I really like the growing maximum owed limit idea and it would be really interesting to also make it possible to set an auto payment threshold lower than it.

The idea being something like "charge at X € owed but let it go up to N*X € if a payment fails before suspending service" where the N scales with something like the number of paid invoices or even total past spend.,

replies(1): >>45236002 #
1. strnisa ◴[] No.45236002[source]
The primary objective of the max-owed limit is to cap per-customer risk.

If you are suggesting that the max-owed limit is actually N×X, then that would multiply worst-case exposure by N, which is undesirable.

If you are suggesting that we charge the customer when they owe X while their max-owed limit is N×X, this would be worse for the customer, since they would pay `N × (X × variable_rate_fee + fixed_rate_fee)` instead of `N×X×variable_rate_fee + fixed_rate_fee` in payment processing fees.

replies(1): >>45236355 #
2. franga2000 ◴[] No.45236355[source]
If your payment processor takes a per-transaction fee (not all do) then yes, this is a slightly worse deal for the customer. However, I think this would still be a good choice to give them, even if many would probably not chose it in order to save a few cents.

If I burn 1 € per day and my max owed based on whatever risk assessment is 20 €, I can set my payment treshold to 15 €, meaning if a payment fails, I have 5 days to fix it and settle the debt before you suspend my access. If the trigger amount is the same as the max owed, I have zero time (well, presumably there is already some wiggle room for the time it takes to process the transaction).

replies(1): >>45236441 #
3. strnisa ◴[] No.45236441[source]
I see what you mean — yes, this could be useful to some customers. We already implement a small grace amount above the max-owed limit that allows for continued service; your idea would essentially allow the customer to increase the default grace amount.