https://github.com/tj/news-api
Go newsletter API backed by DynamoDB
https://github.com/tj/news-api
email email-marketing mailing-list newsletter
Last synced: 7 days ago
JSON representation
Go newsletter API backed by DynamoDB
- Host: GitHub
- URL: https://github.com/tj/news-api
- Owner: tj
- Created: 2019-08-26T14:16:24.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2020-05-29T08:43:15.000Z (over 5 years ago)
- Last Synced: 2025-03-28T18:15:13.471Z (7 months ago)
- Topics: email, email-marketing, mailing-list, newsletter
- Language: Go
- Homepage:
- Size: 5.86 KB
- Stars: 63
- Watchers: 5
- Forks: 4
- Open Issues: 1
-
Metadata Files:
- Readme: Readme.md
- Funding: .github/FUNDING.yml
Awesome Lists containing this project
README
# News API
This tiny API provides subscribing and unsubscribing of users using the [go-news](https://github.com/tj/go-news) package.
## Routes
### GET /subscribers
Responds with all subscribers for a `newsletter`, provided in the query-string parameter.
### POST /subscribe
Accepts a form body with a `newsletter` name and subscriber and `email`.
### GET /unsubscribe
Requires the `newsletter` and `token` query-string parameters. The token must be signed with the __TOKEN_SECRET__ and the included [token](./token) package, this ensures that only people who received an email with this token in their unsubscribe link can perform an unsubscribe.
## Setup
- Create a DynamoDB table with a __Partition Key__ of "newsletter", and a __Sort Key__ of "email".
- Deploy this app however you prefer, you could use [Up](https://github.com/apex/up) for example
- Define the required environment variables:
- __TOKEN_SECRET__: The secret used for signing unsubscribe tokens
- __API_TOKEN__: The API token used to secure sensitive routes (`GET /subscribers`)
- __SUBSCRIBE_REDIRECT_URL__: The redirect URL used for a successful subscription (thank you page)
- __UNSUBSCRIBE_REDIRECT_URL__: The redirect URL used for a successful unsubscribe (bye bye page)
- __DYNAMO_TABLE__: An optional table name, defaults to "news"## Auth
The __API_TOKEN__ is used to restrict access to sensitive routes. You can specify it as the Basic Auth password, no username is necessary, for example:
```
$ export API_TOKEN=hello
$ go run main.go &
$ curl -u :slothy localhost:3000/subscribers?newsletter=blog
```---
[](https://godoc.org/github.com/tj/news-api)

## Sponsors
This project is sponsored by my [GitHub sponsors](https://github.com/sponsors/tj):
[
](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/0)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/1)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/2)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/3)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/4)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/5)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/6)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/7)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/8)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/9)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/10)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/11)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/12)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/13)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/14)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/15)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/16)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/17)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/18)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/19)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/20)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/21)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/22)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/23)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/24)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/25)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/26)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/27)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/28)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/29)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/30)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/31)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/32)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/33)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/34)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/35)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/36)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/37)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/38)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/39)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/40)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/41)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/42)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/43)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/44)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/45)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/46)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/47)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/48)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/49)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/50)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/51)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/52)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/53)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/54)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/55)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/56)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/57)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/58)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/59)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/60)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/61)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/62)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/63)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/64)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/65)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/66)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/67)
[](https://sponsors-api-u2fftug6kq-uc.a.run.app/sponsor/profile/68)