Library / SDK
stripe/stripe-go avatar
stripe/stripe-go

A fresh stripe-go clone does not build until a placeholder in every import path is rewritten

Go library for the Stripe API.

2,652 stars539 forksGoMIT

At a glance

What is it?
stripe/stripe-go is the official Go client for a payments API, generated from a machine readable specification and shaped by the fact that its major version lives in the module path. Two things about it are unusual and both are documented in its own build files: the repository does not compile until a script rewrites a placeholder out of every import, and the current task runner imports a recipe file from a directory outside the repository. Around those sit a two dependency module file, a test suite that runs entirely against a mock, a make file that declares itself deprecated, and three releases published nine minutes apart with the alpha last.
Who is it for?
Use this client if you are writing Go against that API and you want the typed resource surface with generated request and response shapes, because that is the whole product and it is thorough. Three things to know before you wire it in.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 1 day ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • stripe/stripe-go2,652 ★ · +12
Star history
Repository2026-10-042026-11-14
stripe/stripe-go2.6k2.7k

12 Stars in the last 41 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Three releases in nine minutes, with the alpha published last

The three newest releases are a stable minor version and two builds of the next patch, and all three were published on the same morning inside nine minutes. The order is the interesting part: the beta was published at fifty past, and the alpha at five to, so the later number in the sequence carries the earlier stage name. Nothing here suggests anything is wrong, since a beta and an alpha for adjacent targets will be cut close together and the tag order is a matter of when somebody got to it. But if you pin a pre-release build of this library by sorting the release list, you will pick the wrong one, which is a small trap in a repository whose whole value is that its versions are predictable.

The repository does not compile until a placeholder is rewritten

The task file contains a comment that explains the build order better than any documentation could. Before formatting, the Go code in the repository is not syntactically valid, and the reason is given a few lines later: files are generated containing a placeholder in the major version segment of the import path, which a normalisation recipe then replaces with the real number read from the version file at the root. So a fresh clone is not a working tree. It is a template that becomes a working tree when one recipe runs, and that recipe is a chain of file rewrites across the module file, the readme and every Go file it can find. The major version bump is the same problem in a bigger hat, which is why there is a dedicated recipe for it.

The task runner imports a recipe file from outside the repository

One line near the top of the task file imports utilities from a directory beside the repository rather than inside it, and marks the import as optional. Everything else in that file assumes those helpers exist, including the ones for finding a home directory and reading an environment variable. So the documented way to run the project's tests, linting and formatting depends on a sibling checkout that is not part of this repository and is not declared anywhere as a prerequisite. That is an ordinary thing to do inside one organisation's monorepo-adjacent tooling and an awkward thing to meet as a contributor, because the failure mode is a missing recipe rather than a missing dependency, and nothing in the readme mentions it.

Two commands to add it, and the major version sitting in every path

The install is documented in three steps and all three are short. Initialise the module if the project does not have one yet:

sh
go mod init

Then name the library in an import, where the major version is part of the path rather than a separate field:

go
import (
	"github.com/stripe/stripe-go/v87"
	"github.com/stripe/stripe-go/v87/customer"
)

Any normal build, install or test command then resolves and fetches it, and the readme also gives the explicit form:

bash
go get -u github.com/stripe/stripe-go/v87

That suffix is the same one the generated files inside this repository carry as a placeholder until the rewrite described earlier runs, so the path you type in your own project and the path inside the library agree only after that recipe has replaced the placeholder with the number read from the version file. It is the most common reason an import line for this client stops resolving after a version bump, and checking it first costs nothing.

The make file declares itself deprecated and the two disagree on the linter

The make file's first line says it is deprecated and slated for deletion in favour of the equivalent task commands, and then proceeds to define eleven targets anyway. The two files do not agree on how to lint: the make file calls a standalone static analysis binary, while the task file installs and runs a different linter at a pinned major and minor version. Both build, both test and both benchmark the same package, and both invoke the same wrapper program for tests, which is the part that matters. The duplication is the cost of a migration in progress, and the comment marking the older file as deprecated is the kind of note that should disappear within a release cycle and frequently does not.

Two direct dependencies for a payments client

The module file requires two packages directly: a decimal arithmetic library, pinned to an exact version, and a testing library, also listed as a direct requirement rather than a development one. There is a small set of indirect requirements, all of them belonging to the testing library. So the HTTP client, the request signing, the retry behaviour, the JSON handling and the parameter encoding are all built on the standard library, which for a payments client is a deliberate choice rather than an accident, and the exact pin on the decimal library is the kind of detail that matters when the numbers are money. It also means the dependency conversation about this library is short, which is unusual and worth saying plainly before anyone asks.

Every resource is three files and a directory

The top level of the repository is the generated surface, and its shape is regular enough to read as a rule. Each API resource appears as a plain file, a directory of its own, a service file and a test file, so a single resource occupies four root entries and the tree repeats that pattern hundreds of times. There are also hand written helpers sitting in the same space as the generated ones, mixed in alphabetically with them, which is the price of generating into a flat directory rather than into a separate tree. Two version files sit beside the readme, one for the code generator and one for the specification the generator reads, plus a version file for the library itself and a changelog that exists twice, once with an extension and once without.

The older client pattern cannot reach the version 2 interfaces

The readme documents two eras of this library and is clear about which to use. The client type was introduced a few major versions back and is the recommended pattern for every resource. The older resource pattern, where a package level key is assigned and each resource package is called directly, still works and is marked deprecated, with deprecation planned for a future release. The line that matters is in the same paragraph: the newer version 2 interfaces are not supported by that pattern at all. So the deprecation is not cosmetic for anyone using the newer interfaces, and the two ways of authenticating for a connected account are also split between the eras, one taking a header set on the parameters and one taking that account's keys at client construction.

Editorial conclusion

Use this client if you are writing Go against that API and you want the typed resource surface with generated request and response shapes, because that is the whole product and it is thorough. Three things to know before you wire it in. The module path carries the major version, so every import line in your project changes when the library does, and this repository handles that with a repository wide rewrite you can copy. Prefer the newer client type, because the older resource pattern is deprecated and cannot reach the version 2 interfaces at all. And build through the task runner's install step first, since the code does not parse until the placeholder substitution has run.

Frequently asked questions

Which Go version does the Stripe Go library require?

Go 1.24 or newer, under the vendor's language version support policy, which covers versions currently receiving support plus those inside the extended support window. The module file declares the same floor.

How do I install the Stripe Go library?

With Go modules: initialise the module if the project has not, import the library and its resource subpackage, and let the toolchain resolve it, or fetch it explicitly. The module path carries a major version suffix, so import lines change at every major bump.

What is the difference between stripe.Client and the old pattern?

The client type was introduced several major versions ago and is the recommended way to reach every resource. The older resource pattern still works but is deprecated, and it cannot reach the newer version 2 interfaces at all.

Do the Stripe Go tests hit the network?

No. Both the current task runner and the older make target invoke a purpose-built wrapper program that runs the suite against a mock with the race detector enabled, and the coverage target uses the same wrapper.

How does the Stripe Go library authenticate for a connected account?

Two ways: setting an account header on the request parameters, which is the recommended approach, or passing that account's own keys when constructing the client.

Can I build the Stripe Go library from a fresh clone?

Not until a normalisation step runs. Generated files contain a placeholder in the major version segment of the import path, and the task file notes that the Go code is not syntactically valid before that rewrite.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. Releases
  5. stripe/stripe-go on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/stripe-stripe-go.svg)](https://hysenlabs.com/projects/stripe-stripe-go)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/stripe-stripe-go.svg)](https://hysenlabs.com/projects/stripe-stripe-go)

Was this useful?