{"id":16344157,"url":"https://github.com/nya1/zebrahook","last_synced_at":"2025-03-23T00:32:40.702Z","repository":{"id":37477557,"uuid":"482064774","full_name":"nya1/zebrahook","owner":"nya1","description":"Zabrahook is a simple but complete system to fully handle webhooks, inspired by Stripe Webhooks, it depends only on PostgreSQL.","archived":false,"fork":false,"pushed_at":"2022-06-21T16:25:36.000Z","size":104,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-18T15:54:48.607Z","etag":null,"topics":["golang","postgresql","webhook","webhook-server","webhook-service"],"latest_commit_sha":null,"homepage":"","language":"Go","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/nya1.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}},"created_at":"2022-04-15T19:32:23.000Z","updated_at":"2024-04-18T09:03:33.000Z","dependencies_parsed_at":"2022-07-12T16:18:33.902Z","dependency_job_id":null,"html_url":"https://github.com/nya1/zebrahook","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nya1%2Fzebrahook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nya1%2Fzebrahook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nya1%2Fzebrahook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nya1%2Fzebrahook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nya1","download_url":"https://codeload.github.com/nya1/zebrahook/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245040235,"owners_count":20551297,"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":["golang","postgresql","webhook","webhook-server","webhook-service"],"created_at":"2024-10-11T00:27:04.552Z","updated_at":"2025-03-23T00:32:40.195Z","avatar_url":"https://github.com/nya1.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n# Zebrahook\n\nDelegate your webhook needs by using Zebrahook.\n\nZabrahook is a simple but complete system to fully handle webhooks, inspired by Stripe Webhooks, it depends only on PostgreSQL.\n\n\n## Features\n- **Easy to use**\n  - Register webhook endpoints and send an event via REST API, depends only on PostgreSQL.\n- **Event type wildcard support**\n  - Allows to register a webhook endpoint that is subscribed to a subsets of events (e.g. `enabled_events: [\"charges.*\", \"shipment.warehouse.A3001.*\"]`)\n- **Automatic backoff retries and circuit breaker**\n  - If a webhook endpoint is not responding Zebrahook will automatically retry up to 3 times using an exponential backoff strategy (configurable)\n- **Configurable**\n  - Using a json config file or via CLI arguments you can customize request headers, backoff strategy and many more options\n- **Secure**\n  - Each registered webhook endpoints have a different secret key, event content is signed (HMAC SHA256) and timestamped to prevent replay attacks.\n\nIntegrate the REST API in your backend using the [**OpenAPI Spec**](https://generator3.swagger.io/index.html?url=https://raw.githubusercontent.com/nya1/zebrahook/main/gen/http/openapi3.yaml)\n\n\n## Architecture\n\nHTTP Server\n  - This is the REST API that you will call to register new webhook endpoints and submit events\n\n\nWorker, two different types of workers are used to better scale and delivery events\n  - Event mapping worker\n    - Used to map events to webhook endpoints\n\n  - Dispatcher worker\n    - This is the worker that will perform the HTTP request to the webhook endpoint and delivery the event\n\nCheckout the [sequence diagram](./docs/architecture.md) to learn more\n\n## CLI\n\nYou can easily start zebrahook using docker:\n\n```bash\ndocker run -v $PWD/config.json:/config.json -p 3000:3000 -t ghcr.io/nya1/zebrahook --server\n```\n\n### Start the server\n\n```bash\nzebrahook --server\n```\n\n#### Additional Options\n\n- `--http-port \u003cport\u003e`: HTTP port to listen\n\n### Start worker\n\n```bash\nzebrahook --worker \u003ctype\u003e\n```\n\n**NOTE:** `\u003ctype\u003e` must be `eventMapping` or `dispatcher`\n\n\n### Other flags\n\n#### Setup database\n\nZebrahook needs a database with some tables and indexes, to setup your database you can run the following command:\n\n```bash\nzebrahook --setup\n```\n\n#### Create new API Key\n\nAllows to create a new API key used to interact with Zebrahook, this is the only api key that you will need and it's considered an \"admin\" api key as it allows to register endpoints and send events.\n\n```bash\nzebrahook --new-api-key\n```\n\nClear text api key will be printed on screen\n\n\n## Configuration\n\nA json file called `config.json` is needed as a configuration. An example configuration can be found [here](./config.example.json)\n\n\n| JSON Field                                  | CLI Override  | Type    | Required | Default | Description                                                         |\n|---------------------------------------------|---------------|---------|----------|---------|---------------------------------------------------------------------|\n| `encryptionKey`                             | n/a           | string  | yes      |         | used internally to encrypt webhook secrets into the database    |\n| `database.dsn`                              | n/a           | string  | yes      |         | full connection url to PostgreSQL                                   |\n| `webhookRequest.timeoutSecs` | n/a           | number  | no       | 30       | maximum HTTP timeout in seconds         |\n| `webhookRequest.userAgent` | n/a           | string  | no       | Zebrahook       | User-Agent header value     |\n| `webhookRequest.signatureHeaderName` | n/a           | string  | no       | Zebrahook-Signature       | Name of the header that will contain the signature     |\n| `logger.level`                              | `--log-level` | string  | no       | info    | log level, available values: debug, info, warn, error, fatal, panic |\n| `logger.output.json`                        | `--log-json`  | boolean | no       | false   | if true output log as a json                                        |\n| `backoffStrategy.baseSecs` | n/a           | number  | no       | 60       | the minimum seconds used in calculation of the exponential backoff (formula used: `baseSecs**nextAttemptCounter+random(0.0,1.0)`)                                 |\n| `backoffStrategy.maxAttempts` | n/a           | number  | no       | 3       | maximum number of event delivery attempts                                 |\n| `worker.eventMapping.parallelJob`           | n/a           | number  | no       | 1       | how many queue polling jobs to run in parallel                      |\n| `worker.eventMapping.pollingIntervalSecs.min` | n/a           | number  | no       | 0.5     | minimum polling interval in seconds                                 |\n| `worker.eventMapping.pollingIntervalSecs.max` | n/a           | number  | no       | 2       | maximum polling interval in seconds                                 |\n| `worker.dispatcher.parallelJob`             | n/a           | number  | no       | 2       | how many queue polling jobs to run in parallel                      |\n| `worker.dispatcher.pollingIntervalSecs.min` | n/a           | number  | no       | 0.5     | minimum polling interval in seconds                                 |\n| `worker.dispatcher.pollingIntervalSecs.max` | n/a           | number  | no       | 2       | maximum polling interval in seconds                                 |\n\n\n## Acknowledgements\n\n- Built using [goa](https://github.com/goadesign/goa)\n- For PostgreSQL queue using [pgq go module](https://github.com/btubbs/pgq)\n- Crypto utils from [cryptopasta](https://github.com/gtank/cryptopasta)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnya1%2Fzebrahook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnya1%2Fzebrahook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnya1%2Fzebrahook/lists"}