{"_id":"hook0-client","_rev":"7-cf4a84b6f6a3ca6988cbd777d2c6449a","name":"hook0-client","dist-tags":{"latest":"2.0.3"},"versions":{"1.0.0":{"name":"hook0-client","version":"1.0.0","keywords":[],"license":"SSPL-1.0","_id":"hook0-client@1.0.0","maintainers":[{"name":"fgribreau","email":"npm@fgribreau.com"}],"homepage":"https://hook0.com/","dist":{"shasum":"3868ec7b9a539cdd2a2cbdcef35a8476a24b6ee8","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-1.0.0.tgz","fileCount":8,"integrity":"sha512-4b4m3/T4TjUDmIQu68lV2jqFx3kOqcSkcCc9XmS5Fvf9inkx/4uneplA6yHv0tTvYNLfxm0TKjlW7aOzeX0eIA==","signatures":[{"sig":"MEUCIFl97Xf8kzUGJAhbG+NFKmpN0QZN2fb1tF6u6Tc00SraAiEA9hN8WsNPx9R0v2xJD8Szxbe3GDYclqGET1TPKIBBVHQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":25054},"main":"dist/index.js","types":"dist/index.d.ts","authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"gitHead":"2c96123e825575e9908f5cff23d669f63749467a","scripts":{"lint":"eslint .","test":"jest","build":"tsc","check":"prettier --check ./src/**.ts","format":"prettier --write ./src/**.ts","check-full":"npm run --silent check && npm run --silent lint && npm run --silent test","release-major":"npm run --silent check-full && npm run --silent build && npm-release major","release-minor":"npm run --silent check-full && npm run --silent build && npm-release minor","release-patch":"npm run --silent check-full && npm run --silent build && npm-release patch"},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"_npmVersion":"10.1.0","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","directories":{},"_nodeVersion":"23.5.0","dependencies":{"url":"^0.11.4","uuid":"^11.0.5","@types/crypto-js":"^4.2.2"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^29.7.0","eslint":"^9.19.0","ts-jest":"^29.2.5","ts-node":"^10.9.2","prettier":"^3.4.2","@eslint/js":"^9.19.0","typescript":"^5.7.3","@types/jest":"^29.5.14","npm-release":"^1.0.0","typescript-eslint":"^8.22.0"},"_npmOperationalInternal":{"tmp":"tmp/hook0-client_1.0.0_1738832326292_0.3732607442870801","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"hook0-client","version":"1.1.0","keywords":[],"license":"MIT","_id":"hook0-client@1.1.0","maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"homepage":"https://hook0.com/","dist":{"shasum":"2433a68e1000b681686dbdb84b10185818cb673a","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-1.1.0.tgz","fileCount":9,"integrity":"sha512-d9jRPIYYVWmjjo4ssnb7tVRML2kbPfMKph8fvSQPnpDxVl/Bv6pa39RH4Z9bnjpdeZ0LjSWjGYovWPrVR3d6jw==","signatures":[{"sig":"MEUCIQD4fwt38grXlrDH26lBYXjYYHmSoYnfM8VDxQ34MNpWRQIgFua1EAXzoMVS5zhrs8UtC2oRTCUG4WYI23F4i/tPSRw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":29622},"main":"dist/index.js","types":"dist/index.d.ts","authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"gitHead":"5cef320be93ccdb177364babdf6c3d3776e521fd","scripts":{"lint":"eslint .","test":"jest","build":"tsc","check":"prettier --check ./src/{*,**/*}.ts","format":"prettier --write ./src/{*,**/*}.ts","check-full":"npm run --silent check && npm run --silent lint && npm run --silent test","release-major":"npm run --silent check-full && npm run --silent build && npm-release major","release-minor":"npm run --silent check-full && npm run --silent build && npm-release minor","release-patch":"npm run --silent check-full && npm run --silent build && npm-release patch"},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"_npmVersion":"11.11.0","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","directories":{},"_nodeVersion":"24.14.1","dependencies":{"url":"^0.11.4"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.3","eslint":"^9.19.0","ts-jest":"^29.2.6","ts-node":"^10.9.2","prettier":"^3.4.2","@eslint/js":"^9.19.0","typescript":"^5.7.3","npm-release":"^1.0.0","@jest/globals":"^30.1.2","@types/crypto-js":"^4.2.2","typescript-eslint":"^8.22.0"},"_npmOperationalInternal":{"tmp":"tmp/hook0-client_1.1.0_1775468712553_0.11422612348747152","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"hook0-client","version":"2.0.0","keywords":[],"license":"MIT","_id":"hook0-client@2.0.0","maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"homepage":"https://hook0.com/","dist":{"shasum":"5a3d04d515f1c47e471a866caf523709b916667a","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-2.0.0.tgz","fileCount":20,"integrity":"sha512-jvMgrS3gIUSv3xv/iHcgPclsbcFeAbZDMMvxfSLs7L/aaURSyw0z2vvqLtSQWcpgWNyDjDe7LmTKLfsC3RYYIA==","signatures":[{"sig":"MEQCIE8M/QSXZDGA2p1d+CfJ2Hgr1ZrGYfz3lWky/h/veqEFAiBaL4+et/BEGSbHZkw90sydBDFiTyfRm+1BjmQssjcB9Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197523},"main":"dist/index.js","types":"dist/index.d.ts","module":"esm/index.mjs","authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"exports":{".":{"import":{"types":"./esm/index.d.mts","default":"./esm/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./package.json":"./package.json"},"gitHead":"a169bf660326b0d717898c81334e92a8eed70bfb","scripts":{"lint":"eslint .","test":"jest","build":"tsc","check":"prettier --check ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","format":"prettier --write ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","check-full":"npm run --silent check && npm run --silent lint && npm run --silent build && npm run --silent test","release-major":"npm run --silent check-full && npm-release major","release-minor":"npm run --silent check-full && npm-release minor","release-patch":"npm run --silent check-full && npm-release patch","api-surface:update":"ts-node tests/apiSurface.update.ts"},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"_npmVersion":"11.17.0","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.3","eslint":"^9.19.0","ts-jest":"^29.2.6","ts-node":"^10.9.2","prettier":"^3.4.2","@eslint/js":"^9.19.0","fast-check":"^4.9.0","typescript":"^5.7.3","npm-release":"^1.0.0","@jest/globals":"^30.1.2","@types/crypto-js":"^4.2.2","typescript-eslint":"^8.22.0"},"_npmOperationalInternal":{"tmp":"tmp/hook0-client_2.0.0_1787671688220_0.48539807247194","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"name":"hook0-client","version":"2.0.1","keywords":[],"license":"MIT","_id":"hook0-client@2.0.1","maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"homepage":"https://hook0.com/","dist":{"shasum":"f34be0116870f027ccfdb65bef2b777987677b02","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-2.0.1.tgz","fileCount":20,"integrity":"sha512-6STmYfsQHb2JlV3m+XRBAtieDOSr+kAvY8im94Ypl+MLYtmufmHI1TXGM3823pUQ0OUwl24VihF55owIFAI7Ew==","signatures":[{"sig":"MEUCIFonwOiyRquW9HJd67JXMyaDL465QRH/zh30wmRodOcVAiEA3v0YGMuIfAkRQqSwj/hUlHrKrOuU4T+oVbS4+IpT0G8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197523},"main":"dist/index.js","types":"dist/index.d.ts","module":"esm/index.mjs","authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"exports":{".":{"import":{"types":"./esm/index.d.mts","default":"./esm/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./package.json":"./package.json"},"gitHead":"1fa4bd82b0a89ce135657471c52d71ca00cd96ed","scripts":{"lint":"eslint .","test":"jest","build":"tsc","check":"prettier --check ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","format":"prettier --write ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","check-full":"npm run --silent check && npm run --silent lint && npm run --silent build && npm run --silent test","release-major":"npm run --silent check-full && npm-release major","release-minor":"npm run --silent check-full && npm-release minor","release-patch":"npm run --silent check-full && npm-release patch","api-surface:update":"ts-node tests/apiSurface.update.ts"},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"_npmVersion":"11.17.0","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.3","eslint":"^9.19.0","ts-jest":"^29.2.6","ts-node":"^10.9.2","prettier":"^3.4.2","@eslint/js":"^9.19.0","fast-check":"^4.9.0","typescript":"^5.7.3","npm-release":"^1.0.0","@jest/globals":"^30.1.2","@types/crypto-js":"^4.2.2","typescript-eslint":"^8.22.0"},"_npmOperationalInternal":{"tmp":"tmp/hook0-client_2.0.1_1787677193891_0.9631408772349224","host":"s3://npm-registry-packages-npm-production"}},"2.0.2":{"name":"hook0-client","version":"2.0.2","keywords":[],"license":"MIT","_id":"hook0-client@2.0.2","maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"homepage":"https://hook0.com/","dist":{"shasum":"3d0be22193b43b48b8905d4e172c1808b0a7e652","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-2.0.2.tgz","fileCount":20,"integrity":"sha512-S2ZYQ6i05sjADhVBqN2upNkLm+0/2vQTWktJU0bS9Y2DHlz5bDDqYhPyN504zEsWkw5SEY/d2U9X2DxmfKitcg==","signatures":[{"sig":"MEYCIQDCD6w1yfYGRQPOdVARNAYzpz19jxdTnS9Z0OBuKATiogIhAI6QB46qw4VeJZHgoFArJv0W4p4dMIGENq4geMPDifMC","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":197523},"main":"dist/index.js","types":"dist/index.d.ts","module":"esm/index.mjs","authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"exports":{".":{"import":{"types":"./esm/index.d.mts","default":"./esm/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./package.json":"./package.json"},"gitHead":"0330b256eb6bbddad0ee8bd078d211f0f29add7a","scripts":{"lint":"eslint .","test":"jest","build":"tsc","check":"prettier --check ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","format":"prettier --write ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","check-full":"npm run --silent check && npm run --silent lint && npm run --silent build && npm run --silent test","release-major":"npm run --silent check-full && npm-release major","release-minor":"npm run --silent check-full && npm-release minor","release-patch":"npm run --silent check-full && npm-release patch","api-surface:update":"ts-node tests/apiSurface.update.ts"},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"_npmVersion":"11.17.0","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","directories":{},"_nodeVersion":"24.19.0","_hasShrinkwrap":false,"devDependencies":{"jest":"^30.1.3","eslint":"^9.19.0","ts-jest":"^29.2.6","ts-node":"^10.9.2","prettier":"^3.4.2","@eslint/js":"^9.19.0","fast-check":"^4.9.0","typescript":"^5.7.3","npm-release":"^1.0.0","@jest/globals":"^30.1.2","@types/crypto-js":"^4.2.2","typescript-eslint":"^8.22.0"},"_npmOperationalInternal":{"tmp":"tmp/hook0-client_2.0.2_1787697436597_0.9220772354190934","host":"s3://npm-registry-packages-npm-production"}},"2.0.3":{"name":"hook0-client","version":"2.0.3","main":"dist/index.js","module":"esm/index.mjs","types":"dist/index.d.ts","exports":{".":{"import":{"types":"./esm/index.d.mts","default":"./esm/index.mjs"},"require":{"types":"./dist/index.d.ts","default":"./dist/index.js"}},"./package.json":"./package.json"},"scripts":{"build":"tsc","test":"jest","api-surface:update":"ts-node tests/apiSurface.update.ts","lint":"eslint .","format":"prettier --write ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","check":"prettier --check ./{src,tests}/{*,**/*}.ts ./esm/*.{mjs,mts}","check-full":"npm run --silent check && npm run --silent lint && npm run --silent build && npm run --silent test","release-major":"npm run --silent check-full && npm-release major","release-minor":"npm run --silent check-full && npm-release minor","release-patch":"npm run --silent check-full && npm-release patch"},"keywords":[],"authors":["David Sferruzza <david@hook0.com>","François-Guillaume Ribreau <fg@hook0.com>"],"license":"MIT","description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","homepage":"https://hook0.com/","devDependencies":{"@eslint/js":"^9.19.0","@jest/globals":"^30.1.2","@types/crypto-js":"^4.2.2","eslint":"^9.19.0","fast-check":"^4.9.0","jest":"^30.1.3","npm-release":"^1.0.0","prettier":"^3.4.2","ts-jest":"^29.2.6","ts-node":"^10.9.2","typescript":"^5.7.3","typescript-eslint":"^8.22.0"},"gitHead":"d0c230289f7be0f74a4de921ec5f371b7785dd17","_id":"hook0-client@2.0.3","_nodeVersion":"24.20.0","_npmVersion":"11.19.0","dist":{"integrity":"sha512-lqIzSJVZKT4FrEMSGvvbm3GqtVqFB/cokoBZrIOYA1QpGAw8tFIEB0M21SMcRz48pQ9TpbaE2LKzSAiv44vbHg==","shasum":"11267d04e1c8c7265c3f5648c57f5813477f6ed1","tarball":"https://registry.npmjs.org/hook0-client/-/hook0-client-2.0.3.tgz","fileCount":20,"unpackedSize":197523,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIAbXywXhjNSlFI43lNOg+O+a3fc1zY40kvnmhr83JwiBAiAlgWGr310FiwESn8j4BL+QmePDn8mqb1qlbuWDvN5P6Q=="}]},"_npmUser":{"name":"fgribreau","email":"npm@fgribreau.com"},"directories":{},"maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/hook0-client_2.0.3_1787950975193_0.6293747958672611"},"_hasShrinkwrap":false}},"time":{"created":"2025-02-06T08:58:46.292Z","modified":"2026-08-28T21:02:55.542Z","1.0.0":"2025-02-06T08:58:46.473Z","1.1.0":"2026-04-06T09:45:12.715Z","2.0.0":"2026-08-25T15:28:08.376Z","2.0.1":"2026-08-25T16:59:54.030Z","2.0.2":"2026-08-25T22:37:16.768Z","2.0.3":"2026-08-28T21:02:55.337Z"},"license":"MIT","homepage":"https://hook0.com/","keywords":[],"description":"TypeScript SDK for Hook0 Open-Source Webhooks as a service for SaaS","maintainers":[{"name":"dsferruzza","email":"david.sferruzza@gmail.com"},{"name":"fgribreau","email":"npm@fgribreau.com"}],"readme":"<div align=\"center\">\n\n# Hook0 TypeScript SDK\n\n**Send and verify webhooks from Node, in either module system**\n\n<br/>\n\n<img src=\"assets/typescript-flow.svg\" alt=\"How the Hook0 TypeScript SDK sits between your application and your users\" width=\"850\"/>\n\n<br/>\n<br/>\n\n[![npm](https://img.shields.io/npm/v/hook0-client)](https://www.npmjs.com/package/hook0-client)\n[![Documentation](https://img.shields.io/badge/docs-hook0-blue)](https://documentation.hook0.com/docs/sdk-javascript-typescript)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](./LICENSE)\n\n</div>\n\n---\n\n## What is this?\n\nThe TypeScript SDK for [Hook0](https://www.hook0.com/), the open source Webhooks-as-a-Service platform\nfor SaaS applications. It sends events, declares the event types your application uses, verifies the\nsignature of a webhook you receive, and calls every operation the API declares through generated,\ndocumented types.\n\n`require` and `import` both reach it, and the `exports` map says so rather than leaving it to be\ninferred. The ES module half re-exports the compiled CommonJS instead of being a second compilation\nof it, so a dependency tree reaching the package both ways still gets one `Hook0ClientError` class\nrather than two.\n\n## Features\n\n- **Send events** - under an ID the client mints, so a retry cannot duplicate one\n- **Declare event types** - upsert the ones your application emits, in one call\n- **Verify signatures** - HMAC-SHA256 over a bilateral clock window\n- **The whole API, typed** - one type per schema, one class per problem, one method per operation\n- **Bounded everywhere** - attempts, backoff, timeouts, payload and answer, all yours to set\n- **One class, both module systems** - `instanceof` still answers what you meant\n\n---\n\n## Quick Start\n\n### 1. Install\n\n```bash\nnpm install hook0-client\n```\n\nTypeScript resolves the declarations for whichever half it picks, under `bundler`, `node16` and\n`nodenext` alike. The compiled layout is not part of the contract, and reaching into\n`hook0-client/dist/…` is refused at resolution, so import the package.\n\n### 2. Send an event\n\n```typescript\nimport { Event, Hook0Client } from 'hook0-client';\n// or: const { Event, Hook0Client } = require('hook0-client');\n\nconst hook0 = new Hook0Client(\n  'https://app.hook0.com/api/v1',\n  '0d0ea1e0-8b1f-4f4d-9c2a-1b5c9a3d7e21',\n  process.env.HOOK0_TOKEN!\n);\n\nconst eventId = await hook0.sendEvent(\n  new Event(\n    'billing.invoice.paid',\n    JSON.stringify({ invoice: 'in_123' }),\n    'application/json',\n    { environment: 'production' }\n  )\n);\n```\n\n### 3. Verify a webhook you receive\n\n```typescript\nimport { verifyWebhookSignature } from 'hook0-client';\n\ntry {\n  verifyWebhookSignature(signature, rawBody, headers, subscriptionSecret, 300);\n} catch (refused) {\n  // answer 400, and do not act on the delivery\n}\n```\n\nThe clock window is bilateral, so a delivery dated too far ahead is refused exactly like one dated\ntoo far behind, because a window that only looked backwards is one a sender widens by dating its own\ndelivery in the future. A header the signature covers but the request did not carry is refused\nbefore any code is computed.\n\n---\n\n## Configuration\n\nEvery bound one send is held to is yours to set, and every one has a default.\n\n| Bound | Default | What it holds back |\n|-|-|-|\n| `maxAttempts` | 4 | requests one send issues, capped at 16 whatever a policy says |\n| `initialBackoff` | 100 ms | the ceiling of the wait before the first retry |\n| `maxBackoff` | 2 s | the ceiling no single wait between attempts crosses |\n| `maxTotalDelay` | 5 s | the budget every wait of one send shares |\n| `requestTimeout` | 10 s | how long one attempt is given |\n| `maxPayloadBytes` | 1 MiB | the payload, refused before a socket is opened |\n| `maxResponseBytes` | 8 MiB | the body read off a socket |\n| `maxHeadBytes` | 16 KiB | the head of an answer, every line taken together |\n| `maxResponseHeaders` | 64 | header lines one answer may carry |\n| `maxHeaderBytes` | 64 KiB | one header line |\n\nEvery default comes from [`clients/conformance/bounds.json`](https://gitlab.com/hook0/hook0/-/blob/master/clients/conformance/bounds.json),\nthe corpus every Hook0 SDK reads. A number changed there fails every SDK still carrying the old one,\nso no two of them can bound different things.\n\nThe last three bound what the other end may cost you. A server that is broken or hostile can\notherwise stream a head, a header or a body of any length into your process.\n\n```typescript\nimport { Hook0Client, Hook0ClientOptions, RetryPolicy } from 'hook0-client';\n\nconst hook0 = new Hook0Client(apiUrl, applicationId, token, false, new Hook0ClientOptions(\n  new RetryPolicy(\n    4,    // attempts, the first one included\n    100,  // ceiling of the delay before the first retry, in milliseconds\n    2000, // ceiling no single delay ever exceeds, in milliseconds\n    5000  // budget all the delays of one send share, in milliseconds\n  ),\n  10_000,          // longest one attempt is given, in milliseconds\n  1024 * 1024,     // largest event payload the client sends, in bytes\n  8 * 1024 * 1024  // largest answer it reads off the socket, in bytes\n));\n```\n\n---\n\n## Usage\n\n### Sending is idempotent, and retried\n\n`sendEvent` sends every event under an ID it knows, either the one set on the event or a UUIDv7 it\nmints when the event carries none. **Passing no ID does not mean the ID comes from Hook0.** The value comes\nfrom the client, travels with the request, and is what `sendEvent` resolves to.\n\nThat is what makes a retry safe. Hook0 keys events on their ID, so a request repeated after a network\nfailure or a server error ingests the event once rather than twice. Without a client-chosen ID, the\nrepeated request would create a second event and deliver it to every subscriber.\n\nRetrying is limited to what could end differently. A request that got no answer, a server error and\nan instance saying it is being reached faster than it accepts are all retried. A `429` naming a\nspent quota is not, because a quota clears when a plan changes or a day turns, and no send can wait\nfor that. A\n`Retry-After` the answer carries is honoured, clamped to what is left of the delay budget. A retried\nrequest Hook0 answers with `EventAlreadyIngested` reports success, since an earlier attempt of that\nsame send reached the API. The same answer to a *first* attempt is a genuine conflict, and is\nreported as an error.\n\n### Declaring the event types you use\n\n```typescript\nimport { EventType, Hook0ClientError } from 'hook0-client';\n\nconst parsed = EventType.fromString('billing.invoice.paid');\n\nif (parsed instanceof Hook0ClientError) {\n  throw parsed;\n}\n\nconsole.log(parsed.service, parsed.resourceType, parsed.verb);\n```\n\nOnly the ones your application does not declare yet are created, and those are what comes back.\n\n### Calling the rest of the API\n\nEvery operation the API declares is a method of a generated group, one group per entity.\n\n```typescript\nimport { generated } from 'hook0-client';\n\nconst applications = new generated.ApplicationsApi(transport);\n\ntry {\n  const application = await applications.get(applicationId);\n  console.log(application.name);\n} catch (failed) {\n  if (failed instanceof generated.ProblemError && failed.kind === 'NotFound') {\n    // the API named a problem, and this is which one\n  }\n}\n```\n\n---\n\n## Development\n\n`clients/typescript/src/generated/` is written by [`hook0-sdkgen`](https://gitlab.com/hook0/hook0/-/tree/master/clients/sdkgen)\nfrom the OpenAPI snapshot the API commits, and is rewritten whole on every regeneration. A hand edit\nthere is reverted the next time anyone regenerates, and the drift guard says so before that. Change\nthe generator, then run:\n\n```\nUPDATE_SDK=typescript cargo test -p hook0-sdkgen sdk_targets\n```\n\nEverything beside it, the transport, the retry loop and the signature verification, is hand-written\nand never regenerated, and so is `tests/`.\n\nWhat a send retries, the bounds it is held to and how a signature is verified are dictated by the\nshared corpus at [`clients/conformance`](https://gitlab.com/hook0/hook0/-/tree/master/clients/conformance),\nwhich every SDK's suite reads, so a verdict changed there fails this client until it agrees again.\n\nEvery case runs against a real Hook0 over a loopback socket. Nothing here stands in for a part of\nthe client.\n\n```\nnpm install\nnpm run check-full\n```\n\n---\n\n## License\n\nThe Hook0 TypeScript SDK is free and open source, released under the [MIT License](./LICENSE). Use it,\nchange it, ship it, in open source and in commercial work alike, as long as the copyright notice\ntravels with it.\n\nHook0 itself is open source too. Read [what Hook0 is](https://documentation.hook0.com/docs/what-is-hook0),\nvisit [hook0.com](https://www.hook0.com/), join the [community](https://www.hook0.com/community), or\nwrite to [support@hook0.com](mailto:support@hook0.com).\n\nMaintained by [David Sferruzza](mailto:david@hook0.com) and [François-Guillaume Ribreau](mailto:fg@hook0.com).\n","readmeFilename":"README.md"}