The Whop SDK gives you typed access to the Whop API. Pass your API key to the client explicitly — the SDK reads no environment variables, so a client built without a key sends unauthenticated requests and the API answers 401.
API reference documentation is available here.
A full reference for this library is available here.
Instantiate and use the client with the following:
package example
import (
context "context"
whopsdk "github.com/whopio/whopsdk-go/v2"
client "github.com/whopio/whopsdk-go/v2/client"
option "github.com/whopio/whopsdk-go/v2/option"
)
func do() {
client := client.NewWhop(
option.WithToken(
"<token>",
),
)
request := &whopsdk.CreateAccessTokensRequest{}
client.AccessTokens.Create(
context.TODO(),
request,
)
}You can choose between different environments by passing one of the predefined Environments to the
option.WithEnvironment option. Each environment carries the base URL of every service the SDK talks to.
option.WithBaseURL points every request at one arbitrary base URL instead, which is particularly useful in
test environments.
client := client.NewWhop(
option.WithEnvironment(whopsdk.Environments.Production),
)List endpoints are paginated. The SDK provides an iterator so that you can simply loop over the items.
You can also iterate page-by-page using the GetNextPage helper method.
The Page.Results attribute, which contains the relevant list of items returned by the call to the server,
is the only attribute you will need for most use cases. But if need be, several other attributes are available:
Page.Responsecontains the full spec-defined response as returned by the server.Page.StatusCodeandPage.Headerreturns HTTP metadata associated with the call to the server.Page.RawResponsereturns the pagination object if you need to access its fields (likeNext).
// Loop over the items using the provided iterator.
ctx := context.TODO()
page, err := client.Accounts.List(
ctx,
...
)
if err != nil {
return err
}
iter := page.Iterator()
for iter.Next(ctx) {
item := iter.Current()
fmt.Printf("Got item: %v", *item)
}
if err := iter.Err(); err != nil {
return err
}
// Alternatively, iterate page-by-page.
for page != nil {
for _, item := range page.Results {
fmt.Printf("Got item: %v", *item)
}
page, err = page.GetNextPage(ctx)
if errors.Is(err, core.ErrNoPages) {
break
}
if err != nil {
return err
}
}
// Paginated endpoints return a Page with directly accessible headers, status code, and full response
page, err = client.Accounts.List(
ctx,
...
)
if err != nil {
return err
}
// Access response metadata directly from the page
fmt.Printf("Got headers: %v", page.Header)
fmt.Printf("Got status code: %d", page.StatusCode)
// Access the full spec-defined response object
fullResponse := page.Response
// Access individual fields from the pagination object
nextCursor := page.RawResponse.NextStructured error types are returned from API calls that return non-success status codes. These errors are compatible
with the errors.Is and errors.As APIs, so you can access the error like so:
response, err := client.AccessTokens.Create(...)
if err != nil {
var apiError *core.APIError
if errors.As(err, &apiError) {
// Do something with the API error ...
}
return err
}A variety of request options are included to adapt the behavior of the library, which includes configuring
authorization tokens, or providing your own instrumented *http.Client.
These request options can either be specified on the client so that they're applied on every request, or for an individual request, like so:
Providing your own
*http.Clientis recommended. Otherwise, thehttp.DefaultClientwill be used, and your client will wait indefinitely for a response (unless the per-request, context-based timeout is used).
// Specify default options applied on every request.
client := client.NewWhop(
option.WithToken("<YOUR_API_KEY>"),
option.WithHTTPClient(
&http.Client{
Timeout: 5 * time.Second,
},
),
)
// Specify options for an individual request.
response, err := client.AccessTokens.Create(
...,
option.WithToken("<YOUR_API_KEY>"),
)You can access the raw HTTP response data by using the WithRawResponse field on the client. This is useful
when you need to examine the response headers received from the API call. (When the endpoint is paginated,
the raw HTTP response data will be included automatically in the Page response object.)
response, err := client.AccessTokens.WithRawResponse.Create(...)
if err != nil {
return err
}
fmt.Printf("Got response headers: %v", response.Header)
fmt.Printf("Got status code: %d", response.StatusCode)The SDK is instrumented with automatic retries with exponential backoff. A request will be retried as long as the request is deemed retryable and the number of retry attempts has not grown larger than the configured retry limit (default: 2).
Which status codes are retried depends on the retryStatusCodes generator configuration:
legacy (current default): retries on
recommended: retries on
- 408 (Timeout)
- 429 (Too Many Requests)
- 502 (Bad Gateway)
- 503 (Service Unavailable)
- 504 (Gateway Timeout)
If the Retry-After header is present in the response, the SDK will prioritize respecting its value exactly
over the default exponential backoff.
Use the option.WithMaxAttempts option to configure this behavior for the entire client or an individual request:
client := client.NewWhop(
option.WithMaxAttempts(1),
)
response, err := client.AccessTokens.Create(
...,
option.WithMaxAttempts(1),
)Setting a timeout for each individual request is as simple as using the standard context library. Setting a one second timeout for an individual API call looks like the following:
ctx, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
response, err := client.AccessTokens.Create(ctx, ...)If you want to send the explicit null JSON value through an optional parameter, you can use the setters
that come with every object. Calling a setter method for a property will flip a bit in the explicitFields
bitfield for that setter's object; during serialization, any property with a flipped bit will have its
omittable status stripped, so zero or nil values will be sent explicitly rather than omitted altogether:
type ExampleRequest struct {
// An optional string parameter.
Name *string `json:"name,omitempty" url:"-"`
// Private bitmask of fields set to an explicit value and therefore not to be omitted
explicitFields *big.Int `json:"-" url:"-"`
}
request := &ExampleRequest{}
request.SetName(nil)
response, err := client.AccessTokens.Create(ctx, request, ...)While we value open-source contributions to this SDK, this library is generated programmatically. Additions made directly to this library would have to be moved over to our generation code, otherwise they would be overwritten upon the next generated release. Feel free to open a PR as a proof of concept, but know that we will not be able to merge it as-is. We suggest opening an issue first to discuss with us!
On the other hand, contributions to the README are always very welcome!