# README
Too Good To Go API client (tgt-go)
tgt-go is an unofficial Go client library for accessing the Too Good To Go API.
No official Too Good To Go API documentation is available.
Install
go get github.com/filippalach/[email protected]
where X.Y.Z is the version you need.
or
go get github.com/filippalach/tgt-go
for non Go modules usage or latest version.
Usage
Create a new Too Good To Go client, then use the exposed services (Auth, Items, Orders) to
access different parts of the API.
Capabilities
This package provides following functionalities through exposed services:
- Auth Service
- Login - initiate auth process - /auth/vX/authByEmail
- Poll - finish auth process - /auth/vX/authByRequestPollingId
- Refresh - refresh tokens - /auth/vX/token/refresh
- Signup - create account - /auth/vX/signUpByEmail
- Items Service
- List - fetch items - /items/vX/
- Get - fetch specific item - /items/vX/{item_id}
- Favorite - un/set specific item as favorite - /items/vX/{item_id}/setFavorite
- Orders Service
- Active - fetch active orders - /order/vX/active
- Inactive - fetch past/inactive orders - /order/vX/inactive
Apart from that, exported methods such as: SetAuthContext, NewRequest, Do, CheckResponseForErrors can be used to form request from scratch, if service capabilites would happen to be insufficient in any case.
Authentication
Too Good To Go application uses custom authentication process. It consists of 3 steps:
- Initiating Login process with email (Login method of Auth service)
- Clicking link in email received (requires manual intervention)
- Obtaining tokens (Poll method of Auth service)
After successful authentication process with client's Auth service, Too Good To Go auth context will be set and used in every subsequent request, consisting of
- access_token (needed for subsequent requests using Items, Orders service)
- refresh_token (needed for refreshing tokens)
- user_id (needed for subsequent requests using Items, Orders service)
Usage example
package main
import (
"context"
"log"
"os"
"time"
tgtg "github.com/filippalach/tgt-go"
)
func main() {
// Create client with custom user agent and headers. Pass no ClentOpts to get default client.
client, err := tgtg.New(
nil,
tgtg.SetUserAgent("<your custom user agent>"),
tgtg.SetRequestHeaders(map[string]string{"<header>": "<value>"}))
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// Initiate login process with login request.
loginReq := &tgtg.LoginRequest{
DeviceType: "<IOS|ANDROID>",
Email: "<your_email>",
}
loginResp, _, err := client.Auth.Login(context.TODO(), loginReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// Poll to obtain Too Good To Go tokens.
pollReq := &tgtg.PollRequest{
DeviceType: "<IOS|ANDROID>",
Email: "<your_email>",
// Polling ID is returned by Login request.
PollingID: loginResp.PollingID,
}
// Give client time for you to finish authentication process via received email.
log.Println("Check your mailbox, finish login process and wait 2 minutes...")
time.Sleep(2 * time.Minute)
pollResp, _, err := client.Auth.Poll(context.TODO(), pollReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// Refresh tokens - nil body - client's refresh token will be used by default
// since they already got set earlier with sucessful Poll method.
refreshResp, _, err := client.Auth.Refresh(context.TODO(), nil)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// Refresh tokens - with body - specific refresh token will be used.
refreshReq := &tgtg.RefreshTokensRequest{
RefreshToken: refreshResp.RefreshToken,
}
_, _, err = client.Auth.Refresh(context.TODO(), refreshReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// List items.
listItemsReq := &tgtg.ListItemsRequest{
// UserID has to be specified if no SetAuthContext was called
// either manually, or through the Auth service usage.
UserID: pollResp.StartupData.User.UserID,
Radius: 10,
PageSize: 100,
Page: 1,
Origin: &tgtg.Origin{
Latitude: 50.000,
Longitude: 20.000,
},
}
listItemsResp, _, err := client.Items.List(context.TODO(), listItemsReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// Get speicifc's item ID.
itemID := listItemsResp.Items[0].Item.ItemID
// Get specific item
itemReq := &tgtg.GetItemRequest{
// UserID has to be specified if no SetAuthContext was called either
// manually, or through the Auth service usage.
UserID: pollResp.StartupData.User.UserID,
}
_, _, err = client.Items.Get(context.TODO(), itemReq, itemID)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// ...process received item.
// Un/Set specific item as favorite.
favItemReq := &tgtg.FavoriteItemRequest{
IsFavorite: true,
}
_, err = client.Items.Favorite(context.TODO(), favItemReq, itemID)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// ...process received response.
// Check active orders.
activeOrdersReq := &tgtg.ActiveOrdersRequest{
// UserID has to be specified if no SetAuthContext was called either
// manually, or through the Auth service usage.
UserID: pollResp.StartupData.User.UserID,
}
_, _, err = client.Orders.Active(context.TODO(), activeOrdersReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// ...process received response.
// Check all inactive/past orders.
inactiveOrdersReq := &tgtg.InactiveOrdersRequest{
// UserID has to be specified if no SetAuthContext was called either
// manually, or through the Auth service usage.
UserID: pollResp.StartupData.User.UserID,
Paging: tgtg.Paging{
// 0 for all - this API endpoint works really weirdly.
Page: 0,
Size: 200,
},
}
_, _, err = client.Orders.Inactive(context.TODO(), inactiveOrdersReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// ...process received response.
// Signup request.
signupReq := &tgtg.SignupRequest{
CountryID: "<ISO 3166-1 APLHA-2 country code - e.x. GB, IT>",
DeviceType: "<ANDROID|IOS>",
Email: "<your_email>",
Name: "<your_name>",
NewsletterOptIn: false,
PushNotificationOptIn: true,
}
_, _, err = client.Auth.Signup(context.TODO(), signupReq)
if err != nil {
log.Fatal(err)
os.Exit(1)
}
// ...process received response.
}
Versioning
Each version of the client is tagged and the version is updated accordingly.
To see the list of past versions, run git tag
.
Documentation
For details on all the functionality in this library, see the GoDoc documentation.
Contributions
Too Good To Go App is subject of constant changes - some might be tricky to track - that's why we love pull requests!