{"id":20779191,"url":"https://github.com/didil/inhooks","last_synced_at":"2026-04-04T13:37:19.642Z","repository":{"id":164855017,"uuid":"634153397","full_name":"didil/inhooks","owner":"didil","description":"Incoming Webhooks Gateway built with Go. Uses Redis for storage/queueing.","archived":false,"fork":false,"pushed_at":"2026-04-04T11:10:08.000Z","size":358,"stargazers_count":70,"open_issues_count":3,"forks_count":4,"subscribers_count":2,"default_branch":"main","last_synced_at":"2026-04-04T13:08:57.641Z","etag":null,"topics":["gateway","golang","redis","webhook","webhooks"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/didil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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,"zenodo":null}},"created_at":"2023-04-29T08:02:52.000Z","updated_at":"2026-04-04T11:09:15.000Z","dependencies_parsed_at":"2024-06-21T20:29:05.030Z","dependency_job_id":"42e39136-0f32-47e3-aadd-10b6bc74a9ac","html_url":"https://github.com/didil/inhooks","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/didil/inhooks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didil%2Finhooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didil%2Finhooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didil%2Finhooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didil%2Finhooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/didil","download_url":"https://codeload.github.com/didil/inhooks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/didil%2Finhooks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31402276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T10:20:44.708Z","status":"ssl_error","status_checked_at":"2026-04-04T10:20:06.846Z","response_time":60,"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":["gateway","golang","redis","webhook","webhooks"],"created_at":"2024-11-17T13:26:29.959Z","updated_at":"2026-04-04T13:37:19.633Z","avatar_url":"https://github.com/didil.png","language":"Go","funding_links":[],"categories":["Development Tools"],"sub_categories":[],"readme":"[![License: LGPL v3](https://img.shields.io/badge/License-LGPL_v3-blue.svg)](https://www.gnu.org/licenses/lgpl-3.0)\n![CI](https://github.com/didil/inhooks/actions/workflows/ci.yml/badge.svg)\n[![Coverage Status](https://coveralls.io/repos/github/didil/inhooks/badge.svg?branch=main)](https://coveralls.io/github/didil/inhooks?branch=main)\n\n# Inhooks\n\n![Inhooks Logo](logo-no-background.png?raw=true \"Inhooks Logo\")\n\nInhooks aims to be a lightweight incoming webhooks gateway solution. Written in Go and runnable as a single binary or docker container. Only requires a redis database for storage/queueing.\n\nYou can read more about inhooks in the [launch blog post](https://didil.medium.com/inhooks-3983b68274e1).\n\n*Note: This software is still early in its development cycle / not battle-tested. Test thoroughly before using in production systems.*\n\n## Architecture\n\n![Inhooks Architecture](inhooks-architecture.png?raw=true \"Inhooks Architecture\")\n\n### High level overview\nInhooks consists of two major concepts, Sources and Sinks. A Source is an endpoint for receiving webhooks, and a [Sink](https://en.wikipedia.org/wiki/Sink_(computing)) is a target that receives the webhooks.\n\nInhooks listens to HTTP webhooks and saves the messages to Redis. A processing module retrieves the messages and sends them reliably to the defined sinks.\n\n## Features\n- Receive HTTP Webhooks and save them to a Redis database\n- Fanout messages to multiple HTTP targets (sinks)\n- Fast, concurrent processing\n- Supports delayed processing\n- Supports retries on failure with configurable number of attempts, interval and constant or exponential backoff\n- Supports different HTTP payloads types: JSON, x-www-form-urlencoded, multipart/form-data\n- Supports message transformation using JavaScript ECMAScript 5.1\n- ... more features planned\n\n## Downloading release binaries\nThe release binaries are available on the [GitHub releases](https://github.com/didil/inhooks/releases) page.\nTo download a specific version, adjust then env vars below and run:\n```shell\nexport INHOOKS_VERSION=\"0.1.11\"\nexport OS=\"linux\"\nexport ARCH=\"amd64\"\ncurl -LO https://github.com/didil/inhooks/releases/download/v${INHOOKS_VERSION}/inhooks_${INHOOKS_VERSION}_${OS}_${ARCH}.tar.gz\ntar -xvzf inhooks_${INHOOKS_VERSION}_${OS}_${ARCH}.tar.gz\n```\n\n## Docker images:\nThe released docker images are available at: https://github.com/didil/inhooks/pkgs/container/inhooks\n\nA minimal example to run the docker image:\n```\ndocker run -it --rm \\\n-e REDIS_INHOOKS_DB_NAME=myinhooksdb  \\\n-e REDIS_URL=redis://\u003credis_user\u003e:\u003credis_password\u003e@\u003credis_host\u003e:\u003credis_port\u003e \\\n--mount type=bind,source=\"$(pwd)\"/inhooks.yml,target=/app/inhooks.yml,readonly \\\n-p 3000:3000 \\\nghcr.io/didil/inhooks:v0.1.11\n```\n\n## Usage\n### Inhooks config\nThe inhooks config file allows setting up the Source to Sink flows.\nCreate a file named inhooks.yml in the folder where the inhooks server will run (configurable via the INHOOKS_CONFIG_FILE env variable).\n\nExample inhooks.yml config\n``` yaml\nflows:\n  - id: flow-1\n    source:\n      id: source-1\n      slug: source-1-slug\n      type: http\n    sinks:\n      - id: sink-1\n        type: http\n        url: https://example.com/target\n        delay: 90s # delay processing by 90 seconds\n      - id: sink-2\n        type: http\n        url: https://example.com/othertarget\n        retryInterval: 5m # on error, retry after 5 minutes\n        # retryExpMultiplier: 2 # exponential backoff\n        maxAttempts: 10 # maximum number of attempts\n```\n\nWith this config, inhooks will listen to http POST requests to `/api/v1/ingest/source-1-slug`.\n\nWhen a message is received, it is saved to the redis database. Then inhooks tries to send it to each of the urls defined in the sinks section of the config.\nIn case of failures, retries are attempted based on the sink config params.\n\nIf the config is modifed, the server must be restarted to load the new config.\n\n### Env vars\nCopy the .env examples to init the .env file and update as needed (to set the inhooks config file path, the redis url, the server port, etc).\n```shell\ncp .env.example .env\n```\n\n### Securing webhooks\nIf you would like to verify your webhooks with HMAC 256, you can use the following configuration:\n\n``` yaml\nflows:\n  - id: flow-1\n    source:\n      id: source-1\n      slug: source-1-slug\n      type: http\n      verification:\n        verificationType: hmac # only option supported at the moment\n        hmacAlgorithm: sha256 # only option supported at the moment\n        signatureHeader: x-my-header # the name of the http header in the incoming webhook that contains the signature\n        signaturePrefix: \"sha256=\" # optional signature prefix that is required for some sources, such as github for example that uses the prefix 'sha256='\n        currentSecretEnvVar: VERIFICATION_FLOW_1_CURRENT_SECRET  # the name of the environment variable containing the verification secret\n        previousSecretEnvVar: VERIFICATION_FLOW_1_PREVIOUS_SECRET # optional env var that allows rotating secrets without service interruption\n```\n\n### Message transformation\n\n#### Transform definition\n\nMessage transformation allows you to modify the payload and headers of messages before they are sent to the sinks (destinations). This can be useful for tasks such as adding or removing fields, changing the format of the data, or adding custom headers.\n\nCurrently, only JavaScript transformations are supported. The JavaScript function should be named `transform` and should take two parameters: `bodyStr` (the message body as a string) and `headers` (the message headers as a JSON object). The function should return an array with two elements: the transformed payload as a string and the transformed headers as a JSON object.\nThe `headers` fields has the following format:\n```\n{\n  \"header-name\": [\"value1\", \"value2\"]\n}\n```\n\nOnly JavaScript ECMAScript 5.1 is supported at the moment. We use the [goja](https://github.com/dop251/goja) library to execute the JavaScript code. You can read about the limitations on goja's documentation pages.\n\nHere is an example configuration:\n```yaml\nflows:\n  - id: flow-1\n    source:\n      id: source-1\n      slug: source-1-slug\n      type: http\n    sinks:\n      - id: sink-1\n        type: http\n        url: https://example.com/target\n        transform:\n          id: js-transform-1\ntransform_definitions:\n  - id: js-transform-1\n    type: javascript\n    script: |\n      function transform(bodyStr, headers) {\n        const body = JSON.parse(bodyStr);\n\n        // add a header\n        headers[\"X-INHOOKS-TRANSFORMED\"] = [\"1\"];\n        // capitalize the message if present\n        if (body.msg) {\n          body.msg = body.msg.toUpperCase();\n        }\n        // delete a key from the body\n        delete body.my_dummy_key;\n\n        return [JSON.stringify(body), headers];\n      }\n#  alternatively, you can provide the script path\n#   script_path: /path/to/script.js\n```\n\n\n#### Testing transform scripts\n\nYou can use the `/api/v1/transform` endpoint to test your transform scripts before adding them to your flow configuration. This endpoint allows you to simulate the transformation process and see the results immediately.\n\nTo use this endpoint, send a POST request with a JSON payload containing the following fields:\n- `body`: The message body as a string\n- `headers`: The message headers as a JSON object\n- `transformDefinition`: An object containing the `type` and `script` of your transformation\n\nHere's an example of how to use the `/api/v1/transform` endpoint:\n```shell\ncurl -X POST http://localhost:3000/api/v1/transform \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"body\": \"{\\\"msg\\\": \\\"hello world\\\", \\\"my_dummy_key\\\": \\\"value\\\"}\",\n        \"headers\": {\"Content-Type\": [\"application/json\"]},\n        \"transformDefinition\": {\n          \"type\": \"javascript\",\n          \"script\": \"function transform(bodyStr, headers) { const body = JSON.parse(bodyStr); headers[\\\"X-INHOOKS-TRANSFORMED\\\"] = [\\\"1\\\"]; if (body.msg) { body.msg = body.msg.toUpperCase(); } delete body.my_dummy_key; return [JSON.stringify(body), headers]; }\"\n        }\n      }'\n```\n\n\n### Prometheus metrics\nInhooks exposes Prometheus metrics at the `/api/v1/metrics` endpoint.\n\n## Development setup\n### Tools\nGo 1.20+ and Redis 6.2.6+ are required\n\nInstall tools\n```shell\nmake install-tools\n```\n\n### Env\nCopy the .env examples to init the .env files\n```shell\ncp .env.example .env\ncp .env.test.example .env.test\n```\n\n### Run tests\n```shell\nmake test\n```\n\n### Run linter\n```shell\nmake lint\n```\n\n### Run Dev Server\n```shell\nmake run-dev\n```\n\n### Run Docker Compose\n```shell\ndocker-compose up\n```\n\n## Contributing\nFeel free to open new issues or PRs ! You can also reach out to the maintainer at the email address: adil-inhooks@ledidil.com\n\n## License\nCopyright (c) 2023 Adil H.\n\nInhooks is an Open Source project licensed under the terms of the LGPLv3 license.\nPlease see [LICENSE](LICENSE) for the full license text.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdidil%2Finhooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdidil%2Finhooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdidil%2Finhooks/lists"}