{"id":37206086,"url":"https://github.com/airheartdev/duffel","last_synced_at":"2026-01-14T23:44:04.048Z","repository":{"id":37958203,"uuid":"442712481","full_name":"airheartdev/duffel","owner":"airheartdev","description":"Go client for the Duffel flights API","archived":false,"fork":false,"pushed_at":"2024-05-02T12:02:44.000Z","size":1222,"stargazers_count":12,"open_issues_count":3,"forks_count":5,"subscribers_count":2,"default_branch":"main","last_synced_at":"2024-06-21T05:04:58.256Z","etag":null,"topics":["api","duffel","flights","flights-api","generics","go","golang","travel"],"latest_commit_sha":null,"homepage":"https://duffel.com/docs/guides/quick-start","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/airheartdev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-29T08:43:13.000Z","updated_at":"2023-11-03T20:11:26.000Z","dependencies_parsed_at":"2024-06-21T04:21:04.649Z","dependency_job_id":"10b1fc4f-80ed-4233-ac9e-1ce373f39f9c","html_url":"https://github.com/airheartdev/duffel","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/airheartdev/duffel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airheartdev%2Fduffel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airheartdev%2Fduffel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airheartdev%2Fduffel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airheartdev%2Fduffel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/airheartdev","download_url":"https://codeload.github.com/airheartdev/duffel/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/airheartdev%2Fduffel/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28439530,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T22:37:52.437Z","status":"ssl_error","status_checked_at":"2026-01-14T22:37:31.496Z","response_time":107,"last_error":"SSL_read: 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":["api","duffel","flights","flights-api","generics","go","golang","travel"],"created_at":"2026-01-14T23:44:03.441Z","updated_at":"2026-01-14T23:44:04.034Z","avatar_url":"https://github.com/airheartdev.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Duffel API Go Client\n\nA Go (golang) client library for the [Duffel Flights API](https://duffel.com) implemented by the [Airheart](https://airheart.com) team.\n\n[![Tests](https://github.com/airheartdev/duffel/actions/workflows/ci.yaml/badge.svg)](https://github.com/airheartdev/duffel/actions/workflows/ci.yaml)\n\n## Installation\n\nWe've designed this pkg to be familiar and ideomatic to any Go developer. Go get it the usual way:\n\n\u003e NOTE: Requires at least Go 1.18 since we use generics on the internal API client\n\n```shell\ngo get github.com/airheartdev/duffel\n```\n\n## Usage examples\n\nSee the [examples/\\*](/examples/) directory\n\n## Getting Started\n\nThe easiest way to get started, assuming you have a Duffel account set up and an API key ready, is to create an API instance and make your first request:\n\n```go\n// Create a new client:\ndfl := duffel.New(os.Getenv(\"DUFFEL_TOKEN\"))\n```\n\nFor available methods, see:\n\n- [GoDoc Documentation](https://pkg.go.dev/github.com/airheartdev/duffel#section-documentation)\n- [Duffel API reference](https://duffel.com/docs/api/overview/welcome)\n\nAnd familiarise yourself with the implementation notes:\n\n### Monetary amounts\n\nAll models that have fields for an amount and a currency implement a method to return a parsed `currency.Amount{}`\n\n```go\ntotal:= order.TotalAmount() // currency.Amount\ntotal.Currency // USD\ntotal.Amount // 100.00\ntotal.String() // 100.00 USD\n```\n\n### Working with iterators\n\nAll requests that return more than one record will return an iterator. An Iterator automatically paginates results and respects rate limits, reducing the complexity of the overall programming model.\n\n```go\ndfl := duffel.New(os.Getenv(\"DUFFEL_TOKEN\"))\niter := dfl.ListAirports(ctx, duffel.ListAirportsParams{\n  IATACountryCode: \"AU\",\n})\n\nfor iter.Next() {\n  airport := iter.Current()\n  fmt.Printf(\"%s\\n\", airport.Name)\n}\n\n// If there was an error, the loop above will exit so that you can\n// inspect the error here:\nif iter.Err() != nil {\n  log.Fatalln(iter.Err())\n}\n```\n\nWe've added a convenience method to collect all items from the iterator into a single slice in one go:\n\n```go\nairports, err := duffel.Collect(iter)\nif err != nil  {\n  // Handle error from iter.Err()\n}\n\n// airports is a []*duffel.Airport\n```\n\n## Request IDs\n\nEvery response from Duffel includes a request ID that can be used to help debug issues with Duffel support. You should log the request ID for each operation in your app so that you can track down issues later on.\n\n```go\ndfl := duffel.New(os.Getenv(\"DUFFEL_TOKEN\"))\n\n// Request IDs from Iterators:\niter := dfl.ListAirports(ctx, duffel.ListAirportsParams{\n  IATACountryCode: \"AU\",\n})\n\nfor iter.Next() {\n  airport := iter.Current()\n  fmt.Printf(\"%s\\n\", airport.Name)\n\n  if lastRequestID, ok:= iter.LastRequestID(); ok {\n    fmt.Printf(\"Last request ID: %s\\n\", lastRequestID)\n    // Note: each iteration might be from the same page of data with the same request ID.\n  }\n}\n\n// Request IDs from other operations\ndata, err := client.CreateOfferRequest(context.Background(), duffel.OfferRequestInput{}\n// ...\nif lastRequestID, ok:= dfl.LastRequestID(); ok {\n  fmt.Printf(\"Last request ID: %s\\n\", lastRequestID)\n}\n```\n\n## Error Handling\n\nEach API method returns an error or an iterator that returns errors at each iteration. If an error is returned from Duffel, it will be of type `DuffelError` and expose more details on how to handle it.\n\n```go\n// Example error inspection after making an API call:\noffer, err := dfl.GetOffer(ctx, \"off_123\")\nif err != nil {\n  // Simple error code check\n  if duffel.IsErrorCode(err, duffel.AirlineInternal) {\n    // Don't retry airline errors, contact support\n  }\n\n  // Access the DuffelError object to see more detail\n  if derr, ok:= err.(*duffel.DuffelError); ok {\n    // derr.Errors[0].Type etc\n    // derr.IsCode(duffel.BadRequest)\n  }else{\n    // Do something with regular Go error\n  }\n}\n```\n\n### `duffel.IsErrorCode(err, code)`\n\n`IsErrorCode` is a concenience method to check if an error is a specific error code from Duffel.\nThis simplifies error handling branches without needing to type cast multiple times in your code.\n\n### `duffel.IsErrorType(err, typ)`\n\n`IsErrorType` is a concenience method to check if an error is a specific error type from Duffel.\nThis simplifies error handling branches without needing to type cast multiple times in your code.\n\nYou can also check the `derr.Retryable` field, which will be false if you need to contact Duffel support to resolve the issue, and should not be retried. Example, creating an order.\n\n## Implementation status\n\nTo maintain simplicity and ease of use, this client library is hand-coded (instead of using Postman to Go code generation) and contributions are greatly apprecicated.\n\n- [x] Types for all API models\n- [x] API Client\n- [x] Error handling\n- [x] Pagination _(using iterators)_\n- [x] Rate Limiting _(automatically throttles requests to stay under limit)_\n- [x] Offer Requests\n- [x] Offers\n- [x] Orders\n- [x] Seat Maps\n- [x] Order Cancellations\n- [x] Order Change Requests\n- [x] Order Change Offers\n- [x] Order Changes\n- [x] Airports\n- [x] Airlines\n- [x] Equipment (Aircraft)\n- [x] Payments\n- [x] Places\n\n## License\n\nThis source code is licensed under the Apache 2.0 license found\nin the LICENSE file in the root directory of this source tree.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairheartdev%2Fduffel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fairheartdev%2Fduffel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fairheartdev%2Fduffel/lists"}