{"id":17857789,"url":"https://github.com/queicherius/gw2api-client","last_synced_at":"2025-07-22T15:33:51.126Z","repository":{"id":48464474,"uuid":"50965210","full_name":"queicherius/gw2api-client","owner":"queicherius","description":"Javascript wrapper for the official Guild Wars 2 API.","archived":false,"fork":false,"pushed_at":"2025-05-11T16:37:32.000Z","size":626,"stargazers_count":48,"open_issues_count":10,"forks_count":18,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-06-12T04:02:56.149Z","etag":null,"topics":["maintained","npm-package"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/queicherius.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2016-02-03T01:34:53.000Z","updated_at":"2025-05-11T16:37:36.000Z","dependencies_parsed_at":"2024-03-07T04:29:34.649Z","dependency_job_id":"5b2c270a-63fd-4892-aeb1-907a788c30f8","html_url":"https://github.com/queicherius/gw2api-client","commit_stats":{"total_commits":315,"total_committers":9,"mean_commits":35.0,"dds":0.08253968253968258,"last_synced_commit":"a744fa5faff89315a634ed8ed14845f789762db1"},"previous_names":["gw2efficiency/gw2api-client"],"tags_count":81,"template":false,"template_full_name":null,"purl":"pkg:github/queicherius/gw2api-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queicherius%2Fgw2api-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queicherius%2Fgw2api-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queicherius%2Fgw2api-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queicherius%2Fgw2api-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/queicherius","download_url":"https://codeload.github.com/queicherius/gw2api-client/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/queicherius%2Fgw2api-client/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265560417,"owners_count":23788182,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["maintained","npm-package"],"created_at":"2024-10-28T04:03:57.740Z","updated_at":"2025-07-22T15:33:51.090Z","avatar_url":"https://github.com/queicherius.png","language":"JavaScript","readme":"# gw2api-client\n\n[![Build Status](https://img.shields.io/travis/queicherius/gw2api-client.svg?style=flat-square)](https://travis-ci.org/queicherius/gw2api-client)\n[![Coverage Status](https://img.shields.io/codecov/c/github/queicherius/gw2api-client/master.svg?style=flat-square)](https://codecov.io/github/queicherius/gw2api-client)\n[![Greenkeeper badge](https://badges.greenkeeper.io/queicherius/gw2api-client.svg?style=flat-square)](https://greenkeeper.io/)\n[![Bundle Size](https://img.shields.io/bundlephobia/minzip/gw2api-client.svg?style=flat-square)](https://bundlephobia.com/result?p=gw2api-client)\n\n\u003e Javascript wrapper for the official Guild Wars 2 API.\n\n## Install\n\n```bash\nnpm install gw2api-client\n```\n\nThis module can be used for Node.js as well as browsers using [Browserify](https://github.com/substack/browserify-handbook#how-node_modules-works). \n\n## Usage\n\n### Basic usage\n\n```js\nconst client = require('gw2api-client')\n\n// Get an instance of an API client\nlet api = client()\n\n// Optional, but recommended: Set the schema version of the client\napi.schema('2019-03-26T00:00:00Z')\n\n// Optional: Set the language of the client\napi.language('en')\n\n// Optional: Authenticate the client using an API key\napi.authenticate('my-secret-key')\n\n// Get the ids of all items\napi.items().ids().then(items =\u003e console.log(items))\n\n// Get a single item\napi.items().get(123).then(item =\u003e console.log(item))\n\n// Get multiple items\napi.items().many([123, 456]).then(items =\u003e console.log(items))\n\n// Get all items\napi.items().all().then(items =\u003e console.log(items))\n```\n\n### Endpoints\n\n**[You can find all endpoints and their respective function calls in this document.](./docs/endpoints.md)**\n\n### Caching\n\n**[You can find all cache storages (and the interface for custom ones) in this document.](./docs/cache-storages.md)**\n\nBy default, calling any endpoint requests data from the live API. However, you can easily enable caching for all appropriate endpoints by giving the client a cache storage to work with. You can find the default cache times of all endpoints [here](./docs/endpoints.md).\n\n```js\nconst cacheMemory = require('gw2api-client/src/cache/memory')\napi.cacheStorage(cacheMemory())\n\n// This will only call the official API once\napi.items().ids()\n// ...\napi.items().ids()\n\n// When the cache expires, this will call the official API again\napi.items().ids()\n\n// You can skip the cache for guaranteed live data\napi.items().live().ids()\n```\n\n\u003e **Note:** The cache storage save is asynchronous in the background. During this time, the API function already resolves a result for best performance. Therefore it *can* happen that some data gets requested twice, if you request it in rapid succession and are not using a cache that saves in memory (memory or browser caches).\n\nYou can also chain multiple cache storages together. In this case, the cache gets saved in all storages and read from the first storage in the list answering with a valid value. The more persistent and more reliable cache storages should therefore be on the end of the list and the fastest (e.g. memory) should be at the start of the list.\n\n```js\nconst cacheMemory = require('gw2api-client/src/cache/memory')\nconst cacheRedisStorage = require('gw2api-client/src/cache/redis')\n\n// Save in memory and local storage\n// Try to answer from memory first, then from local storage and then hit the API\napi.cacheStorage([\n  cacheMemory(),\n  cacheRedisStorage({ ... })\n])\n```\n\nThe cache uses expiration times and not the build number, because the content of the API can update independently of the build id. This is caused by the internal whitelisting of the API. However, if you want your cache to invalidate when there is a game update, this is easily possible too:\n\n```js\n// configure api.cacheStorage(...) beforehand\n\n// Check the build every 10 minutes and flush the cache if it updated\nsetInterval(() =\u003e api.flushCacheIfGameUpdated(), 10 * 60 * 1000)\n```\n\n### Error handling\n\nYou can use the Promise `catch` to handle all possible errors.\n\n```js\napi.account().bank().catch(err =\u003e {\n  // err.response is the last response object (e.g. err.response.status)\n  // err.content is the parsed body of the response, if available\n  // err.content.text is the error text thrown of the API, if available\n  console.error('Something went wrong', err)\n})\n```\n\nThe API can throw server errors (status \u003e= 500) that don't have a `text` property set. However, most of the time it responds with one of the following errors:\n\n- `endpoint requires authentication`\n- `invalid key`\n- `requires scope \u003cxyz\u003e`\n- `membership required`\n- `access restricted to guild leaders`\n- `page out of range`\n- `no such id`\n- `all ids provided are invalid`\n\n### Retrying\n\nBy accessing the `fetch` instance, you can enable retrying in case the API or the user has problems getting a valid response. You can find the full documentation for retrying [here](https://github.com/queicherius/lets-fetch#retrying).\n\n```js\n// Retry up to 3 times if the status indicates an request error\napi.fetch.retry((tries, err) =\u003e {\n  if (tries \u003e 3) { \n    return false\n  }\n\n  const res = err.response\n  if (res \u0026\u0026 (res.status \u003c 400 || res.status === 403)) {\n    return false\n  }\n\n  return true\n})\n\n// Wait in between retries\napi.fetch.retryWait((tries) =\u003e tries * 100)\n\n// This request will now retry if it fails (e.g. API issues)\napi.items().ids()\n```\n\n### Extending\n\nYou can extend or overwrite the API client with your own endpoints if you wish so. The only thing that is required is an extension of `AbstractEndpoint` to provide all the logic for pagination, bulk, localisation, caching and so on.\n\nIf you need more specific ways to handle data then the already defined ones, take a look at how the existing endpoints handle these edge cases (e.g. in [`/src/endpoints/recipes.js`](/src/endpoints/recipes.js)).\n\n```js\nconst client = require('gw2api-client')\nconst AbstractEndpoint = require('gw2api-client/src/endpoint')\n\n// Get an instance of an API client\nconst api = client()\n\n// Example: Add a new function inside the abstract endpoint\nAbstractEndpoint.prototype.post = function () {\n  console.log(this)\n}\n\n// Example: Define our custom \"items\" endpoint\nclass ItemsEndpoint extends AbstractEndpoint {\n  constructor (client) {\n    super(client)\n    this.baseUrl = 'https://api.my-domain.com' // The base URL of the API\n    this.url = '/items' // The endpoint URL path\n    this.isPaginated = false // If the endpoint supports ?page and ?page_size\n    this.isBulk = true // If the endpoint supports ?ids\n    this.supportsBulkAll = false // If the endpoint supports ?ids=all\n    this.isLocalized = true // If the endpoint supports ?lang\n    this.cacheTime = 5 * 60 // How long to cache the endpoint responses for\n    this.isAuthenticated = true // If the endpoint requires ?access_token\n\n    this.credentials = true // If the endpoint requires credentials (e.g. session cookies)\n  }\n}\n\n// Attach it to the client, either as a new endpoint or overwriting an already existing one\napi.items = () =\u003e new ItemsEndpoint(api)\n\n// Use the new, overwritten endpoint\napi.items().many([123, 456])\n  .then(items =\u003e console.log('Got the items', items))\n  .catch(err =\u003e console.error('Things went badly', err))\n```\n\n### Mocking\n\nIf you want to mock this module in your tests, you can replace the underlying `lets-fetch` library with the provided mock module, e.g. using [rewire](https://github.com/speedskater/babel-plugin-rewire). You can find all available mock methods [here](https://github.com/queicherius/lets-fetch#mocking).\n\n```js\nconst fetchMock = require('lets-fetch/mock')\nconst file = require('./some/file/using/gw2api/client.js')\n\n// Get the variable \"api\" (which would be the initialized api client\n// in your own code) and replace the fetch method with the fetchMock\nfile.__get__('api').fetch = fetchMock\n\n// Use the fetch mock methods as described in the link above\n```\n\n### Debugging\n\nYou can enable debug messages by setting a flag on the client:\n\n```js\nconst client = require('gw2api-client')\nlet api = client()\n\n// Set for specific endpoints\nlet items = api.items().debugging(true).ids().then(items =\u003e console.log(items))\n\n// Set for all endpoints\napi.debugging(true).items().ids().then(items =\u003e console.log(items))\n```\n\n## Tests\n\n```bash\nnpm test\n```\n\n## Licence\n\nMIT\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueicherius%2Fgw2api-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqueicherius%2Fgw2api-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqueicherius%2Fgw2api-client/lists"}