{"id":37094712,"url":"https://github.com/launchpadcentral/recurly","last_synced_at":"2026-01-14T11:39:46.032Z","repository":{"id":57524395,"uuid":"145634170","full_name":"launchpadcentral/recurly","owner":"launchpadcentral","description":"A Recurly API client written in golang. Actively maintained and unit tested.","archived":false,"fork":true,"pushed_at":"2018-08-23T20:58:16.000Z","size":393,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-20T17:54:20.168Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"blacklightcms/recurly","license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/launchpadcentral.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-08-22T00:26:03.000Z","updated_at":"2024-06-20T17:54:20.169Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/launchpadcentral/recurly","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/launchpadcentral/recurly","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchpadcentral%2Frecurly","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchpadcentral%2Frecurly/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchpadcentral%2Frecurly/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchpadcentral%2Frecurly/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/launchpadcentral","download_url":"https://codeload.github.com/launchpadcentral/recurly/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/launchpadcentral%2Frecurly/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28419241,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:47:48.104Z","status":"ssl_error","status_checked_at":"2026-01-14T10:46:19.031Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-14T11:39:45.242Z","updated_at":"2026-01-14T11:39:46.024Z","avatar_url":"https://github.com/launchpadcentral.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Recurly\nRecurly is a Go (golang) API Client for the [Recurly](https://recurly.com/) API.\n\n [![Build Status](https://travis-ci.org/launchpadcentral/recurly.svg?branch=master)](https://travis-ci.org/launchpadcentral/recurly)  [![GoDoc](https://godoc.org/github.com/launchpadcentral/recurly?status.svg)](https://godoc.org/github.com/launchpadcentral/recurly)\n\n## Announcement: Credit Invoice Release \nAs of v2.10, Recurly has released data structure and API changes to support the [credit invoice release](https://docs.recurly.com/docs/credit-invoices-release). All sites created after May 8, 2018, have this turned on automatically. Existing sites must turn it on no later than Nov 1, 2018. New features will be applicable once the feature is turned on; legacy (existing) invoices will continue to use some deprecated features until they are closed. Most new code can coexist with existing, allowing you to write code to support your transition smoothly. Note that the `new_dunning_event` webhook data structure will change and both may be sent while you have both legacy and new invoices with dunning events. Please review the `Parse` and `ParseDeprecated` methods if you listen for this webhook.  Deprecated code will be removed with any library updates no earlier than December 1, 2018. \n\n## References\n * [API Reference](http://godoc.org/github.com/launchpadcentral/recurly)\n * [Recurly API Documentation](https://dev.recurly.com/docs/)\n * [recurly.js Documentation](https://docs.recurly.com/js/)\n * Documentation and examples below. Unit tests also provide thorough examples.\n\n## Installation\nInstall using the \"go get\" command:\n```\ngo get github.com/launchpadcentral/recurly\n```\n\n### Example\n\n```go\nimport \"github.com/launchpadcentral/recurly\"\n```\n\nConstruct a new Recurly Client and then work off of that. For example, to list\naccounts:\n```go\nclient := recurly.NewClient(\"subdomain\", \"apiKey\", nil)\nresp, accounts, err := client.Accounts.List(recurly.Params{\"per_page\": 20})\n```\n\nrecurly.Response embeds http.Response and provides some convenience methods:\n```go\nif resp.IsOK() {\n    fmt.Println(\"Response was a 200-299 status code\")\n} else if resp.IsError() {\n    fmt.Println(\"Response was NOT a 200-299 status code\")\n\n    // Loop through errors (422 status code only)\n    for _, e := range resp.Errors {\n        fmt.Printf(\"Message: %s; Field: %s; Symbol: %s\\n\", e.Message, e.Field, e.Symbol)\n    }\n}\n\nif resp.IsClientError() {\n    fmt.Println(\"You messed up. Response was a 400-499 status code\")\n} else if resp.IsServerError() {\n    fmt.Println(\"Try again later. Response was a 500-599 status code\")\n}\n\n// Get status code from http.response\nif resp.StatusCode == 422 {\n    // ...\n}\n```\n\n## Usage\nThe basic usage format is to create a client, and then operate directly off of each\nof the services.\n\nThe services are (each link to the GoDoc documentation):\n * [Accounts](https://godoc.org/github.com/launchpadcentral/recurly#AccountsService)\n * [AddOns](https://godoc.org/github.com/launchpadcentral/recurly#AddOnsService)\n * [Adjustments](https://godoc.org/github.com/launchpadcentral/recurly#AdjustmentsService)\n * [Billing](https://godoc.org/github.com/launchpadcentral/recurly#BillingService)\n * [Coupons](https://godoc.org/github.com/launchpadcentral/recurly#CouponsService)\n * [CreditPayments](https://godoc.org/github.com/launchpadcentral/recurly#CreditPaymentsService)\n * [Invoices](https://godoc.org/github.com/launchpadcentral/recurly#InvoicesService)\n * [Plans](https://godoc.org/github.com/launchpadcentral/recurly#PlansService)\n * [Redemptions](https://godoc.org/github.com/launchpadcentral/recurly#RedemptionsService)\n * [Subscriptions](https://godoc.org/github.com/launchpadcentral/recurly#SubscriptionsService)\n * [Transactions](https://godoc.org/github.com/launchpadcentral/recurly#TransactionsService)\n * [Purchases](https://godoc.org/github.com/launchpadcentral/recurly#PurchasesService)\n\nEach of the services correspond to their respective sections in the\n[Recurly API Documentation](https://dev.recurly.com/docs/).\n\nHere are a few examples:\n\n### Create Account\n```go\nresp, a, err := client.Accounts.Create(recurly.Account{\n    Code: \"1\",\n    FirstName: \"Verena\",\n    LastName: \"Example\",\n    Email: \"verena@example.com\",\n})\n\nif resp.IsOK() {\n    log.Printf(\"Account successfully created. Hosted Login Token: %s\", a.HostedLoginToken)\n}\n```\n\n### Get Account\n```go\nresp, a, err := client.Accounts.Get(\"1\")\nif resp.IsOK() {\n    log.Printf(\"Account Found: %+v\", a)\n}\n```\n\n### Get Accounts (pagination example)\nAll paginated methods (usually named List or List*) support a ```per_page``` and ```cursor``` parameter. Example usage:\n\n```go\nresp, accounts, err := client.Accounts.List(recurly.Params{\"per_page\": 10})\n\nif resp.IsError() {\n    // Error occurred\n}\n\nfor i, a := range accounts {\n    // Loop through accounts\n}\n\n// Check for next page\nnext := resp.Next()\nif next == \"\" {\n    // No next page\n}\n\n// Retrieve next page\nresp, accounts, err := client.Accounts.List(recurly.Params{\n    \"per_page\": 10,\n    \"cursor\": next,\n})\n\n// Check for prev page\nprev := resp.Prev()\nif prev == \"\" {\n    // No prev page\n}\n\n// Retrieve prev page\nresp, accounts, err := client.Accounts.List(recurly.Params{\n    \"per_page\": 10,\n    \"cursor\": prev,\n})\n```\n\n### Close account\n```go\nresp, err := client.Accounts.Close(\"1\")\n```\n\n### Reopen account\n```go\nresp, err := client.Accounts.Reopen(\"1\")\n```\n\n### Create Billing Info Using recurly.js Token\n```go\n// 1 is the account code\nresp, b, err := client.Billing.CreateWithToken(\"1\", token)\n```\n\n### Update Billing Info Using recurly.js Token\n```go\n// 1 is the account code\nresp, b, err := client.Billing.UpdateWithToken(\"1\", token)\n```\n\n### Create Billing with Credit Card\n```go\nresp, b, err := client.Billing.Create(\"1\", recurly.Billing{\n    FirstName: \"Verena\",\n    LastName:  \"Example\",\n    Address:   \"123 Main St.\",\n    City:      \"San Francisco\",\n    State:     \"CA\",\n    Zip:       \"94105\",\n    Country:   \"US\",\n    Number:    4111111111111111,\n    Month:     10,\n    Year:      2020,\n})\n```\n\n### Create Billing With Bank account\n```go\nresp, b, err := client.Billing.Create(\"134\", recurly.Billing{\n    FirstName:     \"Verena\",\n    LastName:      \"Example\",\n    Address:       \"123 Main St.\",\n    City:          \"San Francisco\",\n    State:         \"CA\",\n    Zip:           \"94105\",\n    Country:       \"US\",\n    NameOnAccount: \"Acme, Inc\",\n    RoutingNumber: \"123456780\",\n    AccountNumber: \"111111111\",\n    AccountType:   \"checking\",\n})\n```\n\n### Creating Subscriptions\nSubscriptions have different formats for creating and reading.\nDue to that, they have a special use case when creating -- a ```NewSubscription```\nstruct respectively. `NewSubscription` structs are only used for creating.\n\nWhen updating a subscription, you should use the ```UpdateSubscription``` struct.\nAll other creates/updates throughout use the same struct to create/update as to read.\n\n```go\n// s will return a Subscription struct after creating using the\n// NewSubscription struct.\nresp, s, err := client.Subscriptions.Create(recurly.NewSubscription{\n    PlanCode: \"gold\",\n    Currency: \"EUR\",\n    Account: recurly.Account{\n        Code:      \"b6f5783\",\n        Email:     \"verena@example.com\",\n        FirstName: \"Verena\",\n        LastName:  \"Example\",\n        BillingInfo: \u0026recurly.Billing{\n            Number:            4111111111111111,\n            Month:             12,\n            Year:              2017,\n            VerificationValue: 123,\n            Address:           \"400 Alabama St\",\n            City:              \"San Francisco\",\n            State:             \"CA\",\n            Zip:               \"94110\",\n        },\n    },\n})\n```\n\n## Working with Null* Types\nThis package has a few null types that ensure that zero values will marshal\nor unmarshal properly.\n\nFor example, booleans have a zero value of ```false``` in Go. If you need to\nexplicitly send a false value, go will see that as a zero value and the omitempty\noption will ensure it doesn't get sent.\n\nLikewise if you attempt to unmarshal empty/nil values into a struct, you will\nalso get errors. The Null types help ensure things work as expected.\n\n### NullBool\nNullBool is a basic struct that looks like this:\n\n```go\nNullBool struct {\n    Bool  bool\n    Valid bool\n}\n```\nThe Valid field determines if the boolean value stored in Bool was intentionally\nset there, or if it should be discarded since the default will be false.\n\nHere's how to work with NullBool:\n```go\n// Create a new NullBool:\nt := recurly.NewBool(true)\n\n// Check if the value held in the bool is what you expected\nfmt.Printf(\"%v\", t.Is(true)) // true\nfmt.Printf(\"%v\", t.Is(false)) // false\n```\n\nIf, however, NullBool looked like this:\n```go\nrecurly.NullBool{\n    Bool: false,\n    Valid: false,\n}\n```\n\nThen those checks will always return false:\n```go\nfmt.Printf(\"%v\", t.Is(true)) // false\nfmt.Printf(\"%v\", t.Is(false)) // false\n```\n\n### NullInt\nNullInt works the same way as NullBool, but for integers.\n\n```go\ni := recurly.NewInt(0)\ni = recurly.NewInt(1)\ni = recurly.NewInt(50)\n```\n\n### NullTime\nNullTime won't breakdown if an empty string / nil value is returned from the Recurly\nAPI. It also ensures times are always in UTC.\n\n```go\nt := time.Now()\nnt := recurly.NewTime(t) // time is now in UTC\nfmt.Println(t.String()) // 2015-08-03T19:11:33Z\n```\n\nYou can then use s.Account.Code to retrieve account info, or s.Invoice.Code to\nretrieve invoice info.\n\n## Transaction errors\nIn addition to the Errors property in the recurly.Response, response also\ncontains a TransactionError field for Transaction Errors.\n\nBe sure to check `resp.TransactionError` for any API calls that may return a transaction\nerror for additional info. The `TransactionError` struct is defined like this:\n```go\nTransactionError struct {\n\tXMLName          xml.Name `xml:\"transaction_error\"`\n\tErrorCode        string   `xml:\"error_code,omitempty\"`\n\tErrorCategory    string   `xml:\"error_category,omitempty\"`\n\tMerchantMessage  string   `xml:\"merchant_message,omitempty\"`\n\tCustomerMessage  string   `xml:\"customer_message,omitempty\"`\n\tGatewayErrorCode string   `xml:\"gateway_error_code,omitempty\"`\n}\n```\n\n[Link to transaction error documentation](https://recurly.readme.io/v2.0/page/transaction-errors).\n\n## Using webhooks\nInitial webhook support is in place. The following webhooks are supported:\n\nAccount Notifications\n - `NewAccountNotification`\n - `UpdatedAccountNotification`\n - `CanceledAccountNotification`\n - `BillingInfoUpdatedNotification`\n - `BillingInfoUpdateFailedNotification`\n\nSubscription Notifications\n - `NewSubscriptionNotification`\n - `UpdatedSubscriptionNotification`\n - `RenewedSubscriptionNotification`\n - `ExpiredSubscriptionNotification`\n - `CanceledSubscriptionNotification`\n - `PausedSubscriptionNotification`\n - `ResumedSubscriptionNotification`\n - `ScheduledSubscriptionPauseNotification`\n - `SubscriptionPauseModifiedNotification`\n - `PausedSubscriptionRenewalNotification`\n - `SubscriptionPauseCanceledNotification`\n - `ReactivatedAccountNotification`\n\n Invoice Notifications\n - `NewInvoiceNotification`\n - `PastDueInvoiceNotification`\n - `ProcessingInvoiceNotification`\n - `ClosedInvoiceNotification`\n\nPayment Notifications\n - `SuccessfulPaymentNotification`\n - `FailedPaymentNotification`\n - `VoidPaymentNotification`\n - `SuccessfulRefundNotification`\n - `ScheduledPaymentNotification`\n - `ProcessingPaymentNotification`\n \n Dunning Event Notifications\n - `NewDunningEventNotification`\n     \nWebhooks can be used by passing an `io.Reader` to `webhooks.Parse`, then using a switch statement with type assertions to determine the webhook returned.\n\nPRs are welcome for additional webhooks.\n\n## License\nrecurly is available under the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchpadcentral%2Frecurly","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flaunchpadcentral%2Frecurly","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flaunchpadcentral%2Frecurly/lists"}