7 ms·
The Stainless SDK Generator
- yencabulator 2y agoFrankly, this looks horrible. Generics and weird calling conventions instead of setting struct fields, no thanks. zone, err: = client.Zones.New(context.Background(), zones.ZoneNewParams { Account: cloudflare.F(zones.ZoneNewParamsAccount { ID: cloudflare.F("023e105f4ecef8ad9ca31a8372d0c353"), }), Name: cloudflare.F("example.com"), Type: cloudflare.F(zones.ZoneNewParamsTypeFull), })
- yreznikova 2y agoGreat solution!
- Harriet_ 2y agoBeen waiting for this! Nice!!
- aazo11 2y agoWe use Stainless. Great team and product.
- mmcclure 2y agoWe're in the process of (slowly) switching our SDKs over to Stainless. I'll be transparent that it hasn't been the easiest/quickest process ever, but the biggest pain point so far is that we were forced to clean up some rough spots around our OpenAPI spec. It was something we needed to do anyway, so definitely not a knock on Stainless, but it did take the first SDK rollout from being a month or two to many months. The biggest reason we started working with Stainless was to migrate from the open source generator process we were struggling with, but actually ended up transitioning our hand-rolled Node/JS SDK first because it's both our most popular SDK and because the fragmentation of the JS ecosystem has been a surprisingly big headache[1]. Went into it for reduced maintenance, came out pleasantly surprised at how useful I was finding my own SDK's features around `for...of` on paginated routes, etc. Congrats on the launch, Stainless crew! [1] https://www.mux.com/blog/keeping-up-with-the-node-ish-ecosystem https://www.mux.com/blog/keeping-up-with-the-node-ish-ecosys...
- goofybozo111 2y ago[flagged]
- morgante 2y agoStainless and Alex have been great to work with! We've partnered with them to incorporate automated migrations for several APIs (ex. https://docs.grit.io/patterns/library/cloudflare_go_v2 https://docs.grit.io/patterns/library/cloudflare_go_v2) and everyone at Stainless is consistently technically brilliant and kind.
- kmlx 2y agowhat’s the difference between this and https://github.com/deepmap/oapi-codegen https://github.com/deepmap/oapi-codegen
- rattray 2y agooapi-codegen looks pretty cool (it seems I starred it some time ago) but for starters, it's Go only. Stainless does a bunch of languages with more on the way. You can see an example of the Go code Stainless produces here: https://github.com/cloudflare/cloudflare-go https://github.com/cloudflare/cloudflare-go (I'm the Stainless founder)
- itslennysfault 2y agoThat one only does Go, but it is just one of many OpenAPI generators. I used openapi-generator and was able to produce SDKs for TypeScript (angular and node), Dart (Flutter), Kotlin (andoird), and Swift (iOS). They worked great for our purposes and I really had no complaints or issues. I guess my question is, what is the key differentiator that Stainless offers above just using OpenAPI and its huge library of existing generators? https://github.com/OpenAPITools/openapi-generator https://github.com/OpenAPITools/openapi-generator
- rattray 2y agoIf it works great for you, that's great – stick with it! From what I've seen, a lot of API developers find that openapi-generator flat-out breaks or produces broken code for their OpenAPI spec (varies language-to-language of course). Beyond hitting the "it just works" mark more often, some other key differentiators: 1. much easier to configure & customize 2. auto-retry with exponential backoff (this is huge for our customers) 3. auto-pagination 4. overall ergonomics of using the SDK 5. internals that look handwritten (some people care, others don't) 6. one-click releases to github & package managers w/ semver, changelogs, etc 7. careful handling of edge cases (eg, will adding a new enum variant cause your Java client to crash?) 8. a long tail of more advanced features, like webhook signature verification, streaming, etc Thanks for the question – hope this helps :)
- Max_Horstmann 2y agoCongrats! Any C# support in the works? :)
- segphault 2y agoYep! C# is on our roadmap, coming up next after we ship support for Ruby. I recently joined the engineering team at Stainless and this was one of the first questions that I asked. I'm a C# enthusiast and worked at Xamarin back in the day, so I'm pretty excited for this feature.
- cyabuggy 2y ago[flagged]
- gp 2y agoThis is a very exciting product - I'm surprised this didn't exist until now. Would love to see C++ support in the future.
- geekodour 2y agois this an alternative to buf.build?
- rattray 2y agobuf.build : protobuf :: stainless : REST (roughly)
- frankfrank13 2y agobuf would require to switch to protobufs, which for most companies is huge switch
- pksunkara 2y agoHow do you guys differ against https://www.speakeasyapi.dev https://www.speakeasyapi.dev and https://www.buildwithfern.com https://www.buildwithfern.com and https://liblab.com https://liblab.com?
- lapusta 2y agoWe've recently evaluated all four platforms—Stainless, Fern, Speakeasy, and Liblab—and here are our key takeaways: Stainless: The standout for maturity and idiomatic code generation. While method signatures across products may look the same, Stainless shines during developing & debugging - making their codebase easier to navigate. They have a practical separation of SDK configuration from OpenAPI specification, setting it apart from others reliant on OpenAPI overlays. The Stainless Studio also proved invaluable for refining our OpenAPI specs during our exploration phase. Fern: Notable for being open-source, though not free. It provides a robust end-to-end Developer Experience, covering everything from SDKs and documentation to Postman collections. Fern uses an internal "Fern Definition" language (~ think Smithy), it's optional and enables capabilities like merging multiple specs, but is adding another layer to navigate in our view. Speakeasy: Moves at a fast pace, which could be a double-edged sword. Rapid iterations may lead to frequent, potentially disruptive updates for customers. A minor gripe was the inclusion of "Speakeasy" in class names, which felt overly branded. Liblab: Initially limited in language support, they've expanded but still lag behind in establishing a strong customer base, which might be a red flag for some adopters. BTW all folks are very approachable and collaborative!
- alalani1 2y agoWhen you say it shines during development and debugging - can you provide examples of what types of problems it solved?
- simplesager 2y agoThanks for the mention! We do move fast and to help manage the changes better we've introduced a number of change management concepts recently like breaking change detection and more controls around semver. The updates can also be stacked by the user into PRs and versions updated and published in one go. Definitely choices that we can guide you through On the Speakeasy branded classes. We got rid of that some time ago based on customer feedback. Check out our new TS generator https://www.speakeasyapi.dev/post/how-we-built-universal-ts https://www.speakeasyapi.dev/post/how-we-built-universal-ts
- TehShrike 2y agoI'm curious to see the output. Most of the time I specifically avoid using the SDK published by the API provider because it's thousands of lines of code when all I need is ten lines wrapping fetch.
- rattray 2y agoWe try to keep it to a minimum, especially in JS (though we have some nice improvements coming soon when we deprecate node-fetch in favor of built-in fetch). The package sizes aren't tiny because we include thorough types and sourcemaps, but the bundle sizes are fairly tidy. Here's an example of a typical RESTful endpoint (Lithic's `client.cards.create()`: https://github.com/lithic-com/lithic-node/blob/36d4a6a70597e9d15153510b97488875c51e034f/src/resources/cards/cards.ts#L26-L28 https://github.com/lithic-com/lithic-node/blob/36d4a6a70597e... Here are some example repos produced by Stainless: 1. https://github.com/openai/openai-node https://github.com/openai/openai-node 2. https://github.com/openai/openai-python https://github.com/openai/openai-python 3. https://github.com/cloudflare/cloudflare-go https://github.com/cloudflare/cloudflare-go 4. https://github.com/Modern-Treasury/modern-treasury-java https://github.com/Modern-Treasury/modern-treasury-java
- jacoblee9315 2y agoCongrats on the launch! Incredible customer list!
- sloanesturz 2y agoWe've been happy customers of Stainless since the beginning. Alex and the team are thoughtful and care a lot about API design. Recommended! https://github.com/increase https://github.com/increase
- GeneticGenesis 2y agoDisclaimer: We're an early adopter of Stainless at Mux. I've spent more of my time than I'd like to admit managing both OpenAPi spec files [1] and fighting with openapi-generator [2] than any sane person should have to. While it's great having the freedom to change the templates an thus generated SDKs you get with using that sort of approach, it's also super time consuming, and when you have a lot of SDKs (we have 6 generated SDKs), in my experience it needs someone devoted to managing the process, staying up with template changes etc. Excited to see more SDK languages come to Stainless! [1] https://www.mux.com/blog/an-adventure-in-openapi-v3-api-code-generation https://www.mux.com/blog/an-adventure-in-openapi-v3-api-code... [2] https://github.com/OpenAPITools/openapi-generator https://github.com/OpenAPITools/openapi-generator
- pm 2y agoA couple of months ago I tried to generate a Swift SDK using Cloudflare's OpenAPI spec with Apple's Swift OpenAPI generator, to no avail. Apple's generator is quite strict from what I can tell, so I'm curious about the differences between Stainless' and Apple's work. (I haven't tried it since then, so it may work now).
- ramijames 2y agoThat is a very nice landing page.
- addcn 2y agoAlex and team are top notch. Met some of their customers who also use Optic and hear great things. Definitely the place to go these days if you have a public API and want it to be as developer friendly as they come.
- androa 2y agoI've been using openapi-generator for this for quite some time. I love the principle, but find that their generators are not all top notch, and the template-based approach is very hard to contribute to. One thing I do not see with Stainless is also using it to generate the server side of the API. We use OpenAPI as a design doc, and generate client SDKs and Datos for the server from the same spec. This gives us pretty solid control over interoperability.
- itslennysfault 2y agoThats what I used at my previous startup and had a lot of luck with it. Our backend used NestJS which allowed us to define APIs and DTOs using decorators which automatically generated OpenAPI json files. Then our clients would load the json and generate their own SDK as a library. It worked extremely well. It worked so well that I don't really understand what problem Stainless is solving. We didn't ship public SDKs. So, maybe that's what I'm missing, but for our internal clients OpenAPI generators worked great. We generated SDKs on the fly for TypeScript (Node services and Angular clients), Dart (flutter), Kotlin (android), and Swift (iOS). For the most part it all "just worked" for our use case.
- rattray 2y ago> We didn't ship public SDKs. So, maybe that's what I'm missing Yeah, Stainless is more focused on public SDKs, which can be a lot trickier and more demanding. Some more details replying to your other comment here: https://news.ycombinator.com/item?id=40148629 https://news.ycombinator.com/item?id=40148629
- Bjartr 2y ago> their generators are not all top notch, and the template-based approach is very hard to contribute to. I agree, I love them in theory, but wrangling mustache templates is a hassle. They end up super coupled to the code that populates them which makes them a bear to modify.
- brandur 2y agoI helped maintain the public API language bindings at Stripe for many years, and although I'd defend it to the death as the right DX (SDKs are so much easier to use than raw web APIs), it's hard to appreciate just how onerous of a process this was before Alex pioneered a codegen-based solution. Some of the language SDKs were dynamic (e.g. Ruby, Python) and could adapt automatically to small API changes like if a new field was added in a response. Some were not (e.g. Java, Go), and for every API change, someone had to manually make the change to that SDK's codebase (add a field, add a struct, add a function for a new endpoint), get it reviewed and merged, and cut a release. As Stripe got bigger and there were API changes all the time, the only way this was even remotely functional was that we had a couple heroic workhorses that'd watch for changes and open hundreds of PRs a year for them. Honestly, in retrospect, it's amazing this even worked. Getting everything switched over to a generated solution was an arduous process because the new generated code had to be API-compatible with the existing code so that the cutover to generated bindings didn't break every Stripe user under the sun. We eventually got there, but it took a long time. I like Stainless' mission because after seeing the crazy maintenance hassle that all of this was at Stripe, I think it makes way more sense to save all that engineering time for your more concerns, and outsource this problem to someone else. A plug-and-play way of getting high quality SDKs in all common languages that get pushed to appropriate repositories for distribution and comes with quality companion documentation. We've actually had pretty good luck at my current job with open source tools like openapi-generator [1], but this sort of codegen is so convoluted that the sustainability of a pure open source solution makes me a little afraid, and you still end up doing a lot of the last mile work yourself. --- [1] https://github.com/OpenAPITools/openapi-generator https://github.com/OpenAPITools/openapi-generator
- mythz 2y agoNever been a fan of code-gen solutions that generates both DTOs and client proxies which IMO promotes a lot of fragile code-gen that's less resilient to changes. The solution we've adopted in ServiceStack to solve this with minimal code generation and better reusability is to only generate the message-based Typed DTOs for each language but have them able to be used by the same generic JSON ServiceClient. This approach takes minimal effort since we only need to generate Typed DTOs in each language, which all works the same way, where you use the same generic `JsonServiceClient` (created once per language/platform) that use same methods to make API requests making it easy to for our built-in API Explorer [1] (Live Demo [2]) to auto generate API pages for all 11 supported languages which also supports dynamic languages like JS/TS, Python and PHP with additional type hints [3]. [1] https://docs.servicestack.net/api-explorer#code-tab https://docs.servicestack.net/api-explorer#code-tab [2] https://vue-vite-api.jamstacks.net/ui/QueryBookings?tab=code https://vue-vite-api.jamstacks.net/ui/QueryBookings?tab=code [3] https://docs.servicestack.net/add-servicestack-reference https://docs.servicestack.net/add-servicestack-reference
- jenanwise 2y agoI’ve been working with the Stainless team over the last year, and I rapidly went from being highly skeptical of outsourcing SDKs to being one of the team’s biggest fans. Separately, as a consumer of many afterthought-ish SDKs for popular services, I’m extremely excited to see their work opening up to more developers. I hope it raises the bar for SDKs everywhere!
- ezekg 2y agoI run an API SaaS and this looks great. I've wanted to add more SDKs to my lineup, but it's a big commitment for a single person to maintain. Right now, I have a minimal Go SDK to test the waters and definitively see how much effort it takes. One hurdle I have with services like Stainless (which looks great!) is that I don't know where to start to actually codegen an OpenAPI spec from a Ruby/Rails API. Writing and maintaining the spec by hand sounds like a nightmare for any decent sized API, but I guess it's not worse than maintaining multiple SDKs (or even one). How did Stripe handle this?
- amne 2y agoFrom experience I can tell you that you just need to do it manually. And keep maintaing the spec manually. That keeps you aware of it. It is your contract with the outside world. You don't want tools to automatically update it everytime you push. On the contrary, you want tools to slap you hard every time you push and you forgot to update the spec. Now you're going to think hard why did you change the spec and if you maybe need to bump to /api/v2/* As far as generating the first spec from an existing API I think there was shown here on HN a while ago a tool that can generate the spec from you just "browsing" the API with developer tools or something. Maybe even from a HAR file IIRC.
- rattray 2y ago> I don't know where to start to actually codegen an OpenAPI spec from a Ruby/Rails API… How did Stripe handle this? Stripe built their own Ruby DSL for exactly this, and it worked great. It looked something like this: class CreateCustomerMethod < AbstractAPIMethod endpoint "post /v1/customers" returns CustomerAPIResource required :name, String, description: "The name of the customer." optional :description, String, description: "Additional information about the customer." def execute # … end end Unfortunately, I don't know of an open-source equivalent for Ruby; FastAPI in Python is the closest I know of in any language. At Stainless, we're building a TypeScript version of this, but it's still deep in dogfooding. Most people just end up maintaining by hand and using a tool like Optic or Akita to check that it's not wildly out-of-date.
- shidoshi 2y agoCongrats, folks.
- htunnicliff 2y agoQuestion for Stainless folks: For Node.js/JavaScript SDKs, did you consider using Proxy instances in lieu of classes for each resource, to reduce the amount of actual code generated?
- rattray 2y agoYeah, we opted for classes like this to ensure simple, reliable static typing. The amount of runtime code generated per endpoint is typically around 3 short lines – here's an example, also posted elsewhere on this thread: https://github.com/lithic-com/lithic-node/blob/36d4a6a70597e9d15153510b97488875c51e034f/src/resources/cards/cards.ts#L26-L28 https://github.com/lithic-com/lithic-node/blob/36d4a6a70597e...
- ucarion 2y agoLots of these have been popping up lately, they all seem really good. This is the first one I've seen with an answer for "I want to customize the output by hand", which is neat. https://buildwithfern.com/ https://buildwithfern.com/ https://liblab.com/ https://liblab.com/ https://www.speakeasyapi.dev/ https://www.speakeasyapi.dev/ Between this and fancy API doc generators (Mintlify, etc.), I feel like we're finally getting close to being able to just go from OpenAPI to Stripe-level "polish".
- dgellow 2y agoWe have to improve our docs a lot, but yes, that’s the goal! You as a stainless user should feel empowered and in control :)
- deleted 2y ago[deleted]
- bterlson 2y agoGrats on the release! It will be awesome to see how far y'all can push codegen quality from an OpenAPI source of truth. I worked on this extensively inside Azure and I know it is not an easy problem (and with more JSON Schema coming in 3.1/4.0, it is only getting harder). There are a lot of API patterns that you want to expose purpose built client abstractions for. Pagination is a big example. If you stick to OpenAPI, you have to ensure your specs use the patterns your client generator recognizes, and it's not always trivial for authors to know how to express that pattern and for your codegen to infer that pattern. In Azure we tended to rely more on custom extensions to OpenAPI because it made the contract a lot clearer and less error prone, but then you lose interoperability. One thing to consider - I work on TypeSpec[1], and one of the main reasons we built it is to allow encapsulation and reuse of patterns in a first-class way. So, rather than the contract being "endpoints which declare parameters and/or return types with these shapes are inferred to be paginated endpoints", the contract can be "use Page<T>" and the emitted OpenAPI conforms to the contract without effort. It would be fun to see a Stainless TypeSpec library for all the patterns your codegen supports! 1: https://typespec.io https://typespec.io
- ashryan 2y agoI’ve been keeping a simple list of SDK generators here: https://gist.github.com/ashryanbeats/7806079820e0c83b35b94ae867289850 https://gist.github.com/ashryanbeats/7806079820e0c83b35b94ae... Nothing fancy but maybe more helpful than picking through SEO articles in you’re looking for options.
- bgentry 2y agoI was fortunate to be able to watch Stainless evolve while at Mux when we were evaluating it to replace open source & homegrown generators. Alex & team were incredibly responsive to feedback throughout, and the product improved quickly. Generated code has a bad rap for results that are not idiomatic or user-friendly, but I think it's clear that it doesn't have to be that way—getting it right just takes a lot of care and effort that is typically overlooked. Stainless is definitely best-in-class here as far as I've seen.
- nknj 2y agoProud to have Stainless as a partner at OpenAI. All our SDKs are generated by them. Alex, Robert, Philip and team are extremely thoughtful about SDK design and push us to improve our API + other products while they're at it. Stainless is bringing a new standard of SDKs to our industry and this is a great thing for all developers.
- vvoyer 2y agoWhat about jsii? The technology behind AWS cdk sdks: https://aws.github.io/jsii/ https://aws.github.io/jsii/ Is Stainless similar, different?
- rattray 2y agoVery different! Stainless crafts each language's SDK generator around its specific idioms.
- enepture 2y agoCongratulations to Alex and the team. After chatting with them recently at a NYC meet-up, you can tell they live and breathe client SDK generation. They are thoughtful about creating an excellent experience for those generating SDKs (Stainless Studio) and those consuming them. Good luck!
- serjester 2y agoOut of curiosity how difficult has it been hosting OpenAI's SDK? Is there one off stuff that goes into that? Their API seems really challenging - SSE's, tons of complex generics, async, docs - it's endless. Really impressive stuff, I can't imagine doing all this with a team as lean as yours.
- rattray 2y agoIt definitely isn't easy, but it's the kind of challenges we love! You mentioned many of the big ones, but there's also just the sheer scale of the userbase, which means the libraries will be run under every permutation of runtime and configuration under the sun. It's a lot of edge cases to get right! Their team is great to work with, which helps make it worth it. (Note that a lot of the SSE type stuff we do generally so we're able to support a variety of AI companies and other streaming use cases, though disclaimer it is a premium feature)
- beastman82 2y agoIs gRPC too easy or ?
- twitchard 2y agoCongratulations to Alex and team! Had the pleasure of working with Alex on SDK generators back in 2019 and 2020 and it's very exciting to see these ideas and the fruits of this become available to the entire world. Stainless would definitely be where I looked first if I were starting a developer-facing SaaS today.
- simplesager 2y agoCongratulations to the Stainless team on a fantastic launch! I'm one of the co founders of Speakeasy (https://www.speakeasyapi.dev/ https://www.speakeasyapi.dev/). We do similar things in the SDK space and some other things too. I resonate with a lot of what is said in the comments. Last mile API tooling is underrated and most companies don't have the deep API platform expertise to build from scratch. The OSS options in the space proved SDK generation could be done but the actual product that you got in hand still needed a lot of work to be enterprise ready. The code was poor quality, wasn't customisable and there was no change management story. We're seeing a new wave of work in this space that's making api platform engineering much more accessible. The API devex story starts with SDK creation and maintenance but there is a lot more to come!
- tango12 2y agoLove this! Curious, wouldn’t this be great for folks with internal APIs as well? Team 1 can consume team 2’s API with an SDK instead of a raw REST client.