{"id":39884822,"url":"https://github.com/theriverman/taigo","last_synced_at":"2026-01-18T14:36:01.077Z","repository":{"id":41505577,"uuid":"264673566","full_name":"theriverman/taigo","owner":"theriverman","description":"TAIGO is a driver written in GO for Taiga","archived":false,"fork":false,"pushed_at":"2025-06-17T10:44:16.000Z","size":1154,"stargazers_count":14,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-11-22T13:10:46.666Z","etag":null,"topics":["api","driver","go","golang","library","rest","taiga"],"latest_commit_sha":null,"homepage":"https://github.com/theriverman/taigo","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/theriverman.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}},"created_at":"2020-05-17T13:31:14.000Z","updated_at":"2025-09-13T06:35:29.000Z","dependencies_parsed_at":"2024-06-20T05:41:42.476Z","dependency_job_id":"a2ead3dc-4578-4a30-a78a-146b6cbbc636","html_url":"https://github.com/theriverman/taigo","commit_stats":null,"previous_names":[],"tags_count":24,"template":false,"template_full_name":null,"purl":"pkg:github/theriverman/taigo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theriverman%2Ftaigo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theriverman%2Ftaigo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theriverman%2Ftaigo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theriverman%2Ftaigo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theriverman","download_url":"https://codeload.github.com/theriverman/taigo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theriverman%2Ftaigo/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28537803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-18T13:04:05.990Z","status":"ssl_error","status_checked_at":"2026-01-18T13:01:44.092Z","response_time":98,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: 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":["api","driver","go","golang","library","rest","taiga"],"created_at":"2026-01-18T14:36:00.549Z","updated_at":"2026-01-18T14:36:01.042Z","avatar_url":"https://github.com/theriverman.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"TAIGO\n-----\n\n[![Go](https://github.com/theriverman/taigo/actions/workflows/go.yml/badge.svg)](https://github.com/theriverman/taigo/actions/workflows/go.yml)\n[![GoDoc](https://godoc.org/github.com/theriverman/taigo?status.svg)](https://pkg.go.dev/github.com/theriverman/taigo?tab=doc \"Docs @ pkg.go.dev\")\n[![Go Report Card](https://goreportcard.com/badge/github.com/theriverman/taigo)](https://goreportcard.com/report/github.com/theriverman/taigo)\n![Taigo Banner](assets/banner_627x300.png \"TAIGO Banner\")\n\n\n# Description\n**Taigo** is a driver written in GO for [Taiga](https://github.com/taigaio) targeting to implement all publicly available API v1 endpoints. \u003cbr\u003e\nTaiga is an Agile, Free and Open Source Project Management Tool.\n\nShould you have any ideas or recommendations, feel free to report it as an issue or open a pull request.\n\nFor the most recent changes, see [CHANGELOG](./CHANGELOG.md).\n\n## Known Limitations\n  * Some model members holding integers (i.e. `backlog_order`) were implemented using `int` instead of `int64` or rather `uint64` in some cases which results in runtime errors on machines with **32-bit arm** CPUs.\n\n# Integration\nDownload **Taigo**:\n```bash\ngo get github.com/theriverman/taigo\n```\nImport it into your project: \u003cbr\u003e\n```go\nimport (\n    taiga \"github.com/theriverman/taigo\"\n)\n```\n\n# Documentation\nDocumentation is located at [pkg.go.dev/Taigo](https://pkg.go.dev/github.com/theriverman/taigo?tab=doc).\n\n# Architecture\nTo use **Taigo**, you must instantiate a `*Client`, and authenticate against Taiga to either get a new token or validate the one given. To authenticate, use one of the following methods:\n  * `client.AuthByCredentials`\n  * `client.AuthByToken`\n\nAll Taiga objects, such as, Epic, User Story, Issue, Task, Sprint, etc.. are represented as a struct.\u003cbr\u003e\n\n## Meta System\nSince the API endpoints of Taiga return various payloads for the same object types, a meta system has been added \nto simplify the interaction with the **Taigo** APIs. \u003cbr\u003e\n\nFor example, in Taiga the `http://localhost:8000/api/v1/userstories` endpoint can return the following payload types:\n  - User story detail\n  - User story detail (GET)\n  - User story detail (LIST)\n\nThe returned payload type depends on the executed action: list, create, edit, get, etc..\n\nSince Go does not support generics and casting between different types is not a trivial operation, a generic type has been introduced in **Taigo** for each implemented basic object type (Epic, Milestone, UserStory, Task, etc..) found in Taiga.\n\nThese generic types come with meta fields (pointers) to the originally returned payload.\nIn case you need access to a field *not* represented in the generic type provided by **Taigo**, you can use the appropriate meta field.\n\nFor example, struct `Epic` has the following meta fields:\n\n```go\ntype Epic struct {\n    ID                int\n    // ...\n    EpicDetail        *EpicDetail\n    EpicDetailGET     *EpicDetailGET\n    EpicDetailLIST    *EpicDetailLIST\n}\n```\n\nThe available meta field is always stated in the operation's docstring as `Available Meta`, for example:\n```go\n// CreateEpic =\u003e https://taigaio.github.io/taiga-doc/dist/api.html#epics-create\n//\n// Available Meta: *EpicDetail\nfunc (s *EpicService) Create(epic Epic) (*Epic, error) {}\n```\n\n## Docs-As-Code ( godoc / docstrings )\nTo avoid creating and maintaining a redundant API documentation for each covered Taiga API resource, \nthe API behaviours and fields are **not** documented in **Taigo**.\nInstead, the docstring comment provides a direct URL to each appropriate online resource.\u003cbr\u003e\n**Example:**\u003cbr\u003e\n```go\n// CreateEpic =\u003e https://taigaio.github.io/taiga-doc/dist/api.html#epics-create\nfunc (s *EpicService) Create(epic Epic) (*Epic, error) {}\n```\n\nUpon opening that link, you can find out what fields are available through `*Epic`:\n  \u003e - project (required): project id \u003cbr\u003e\n  \u003e - subject (required) \n\nTo find out which operation requires what fields and what they return, always refer to the official \n[Taiga REST API](https://taigaio.github.io/taiga-doc/dist/api.html) documentation.\n\n## Pagination\nIt is rarely useful to receive results paginated in a driver like **Taigo**, so **pagination is disabled** by default. \u003cbr\u003e\n\nTo enable pagination (for all future requests) set `Client.DisablePagination` to `false`: \u003cbr\u003e\n```go\n// Enable pagination (disabled by default)\nclient.DisablePagination(false)\n```\n\nIf you enable pagination, you can collect pagination details by accessing the returned `*http.Response`, \u003cbr\u003e\nand extracting the relevant headers into a taigo.Pagination struct the following way:\n```go\n// Collect returned Pagination headers\np := Pagination{}\np.LoadFromHeaders(client, response)\n```\n\n**Note:** See `type Pagination struct` in [TAIGO/common.models.go](common.models.go) for more details.\n\nFor details on Taiga's pagination, see [Taiga REST API / Pagination](https://taigaio.github.io/taiga-doc/dist/api.html#_pagination).\n\n# Usage\n\n## Client Instantiation\n```go\npackage main\n\nimport (\n  \"fmt\"\n  \"net/http\"\n\n  taiga \"github.com/theriverman/taigo\"\n)\nfunc main() {\n\t// Create client\n\tclient := taiga.Client{\n\t\tBaseURL:    \"https://api.taiga.io\",\n\t\tHTTPClient: \u0026http.Client{},\n\t}\n\t\n\t// Authenticate (get/set Token)\n\tif err := client.AuthByCredentials(\u0026taiga.Credentials{\n\t\tType:     \"normal\",\n\t\tUsername: \"admin\",\n\t\tPassword: \"123123\",\n\t}); err != nil {\n\t\tpanic(err)\n\t}\n\n\t// Get /users/me\n\tme, _ := client.User.Me()\n\tfmt.Println(\"Me: (ID, Username, FullName)\", me.ID, me.Username, me.FullName)\n\n  \t// Get Project (by its slug)\n\tslug := \"therivermantaigo-taigo-public-test\"\n\tfmt.Printf(\"Getting Project (slug=%s)..\\n\", slug)\n\tproject, err := client.Project.GetBySlug(slug)\n\tif err != nil {\n\t\tfmt.Println(err)\n\t}\n\tfmt.Printf(\"Project name: %s \\n\\n\", project.Name)\n}\n```\n\n## Basic Operations\n```go\n// get all projects (no filtering, no ordering)\nprojectsList, _ := client.Project.List(nil)\nfor _, proj := range *projectsList {\n    fmt.Println(\"Project ID:\", proj.ID, \"Project Name:\", proj.Name)\n}\n/*\n  ListProjects accepts a `*ProjectsQueryParameters` as an argument, but if you don't need any filtering, you can pass in a nil.\n*/\n\n// get all projects for user ID 1337\nqueryParams := taiga.Project.QueryParameters{\n    Member: 1337,\n}\nqueryParams.TotalFansLastMonth() // results are ordered by TotalFansLastMonth\nprojectsList, _ := client.Project.List(\u0026queryParams)\nfor _, proj := range *projectsList {\n    fmt.Println(\"Project ID:\", proj.ID, \"Project Name:\", proj.Name)\n}\n\n// upload a file (Create an Epic attachment)\nnewAttachment, err := client.Epic.CreateAttachment(\u0026taiga.Attachment{ObjectID: 1337, Project: 7331}, \"C:/Users/theriverman/Pictures/nghfb.jpg\")\n```\n\n## Non-Standard Operations (Non-Standard)\n1. Clone Epic (with UserStories) -- To be implemented\n2. Clone Epic (without UserStories) -- ✔ Implemented\n3. Clone UserStory (with sub-tasks) -- To be implemented\n4. Clone UserStory (without sub-tasks) -- ✔ Implemented\n5. Clone Sub-Task -- To be implemented\n6. Copy UserStory to another project [will lose comments and attachments] -- To be implemented\n\n## Advanced Operations\nDo you need access to a non yet implemented or special API endpoint? No problem! \u003cbr\u003e\nIt is possible to make requests to custom API endpoints by leveraging `*RequestService`.\n\nHTTP operations (`GET`, `POST`, etc..) should be executed through `RequestService` which provides a managed environment for communicating with Taiga.\n\nFor example, let's try accessing the `epic-custom-attributes` endpoint:\n\nFirst, a model struct must be created to represent the data returned by the endpoint. Refer to the official Taiga API documentation for response examples:\n```go\n// EpicCustomAttributeDetail -\u003e https://taigaio.github.io/taiga-doc/dist/api.html#object-epic-custom-attribute-detail\n// Converted via https://mholt.github.io/json-to-go/\ntype EpicCustomAttributeDetail struct {\n\tCreatedDate  time.Time   `json:\"created_date\"`\n\tDescription  string      `json:\"description\"`\n\tExtra        interface{} `json:\"extra\"`\n\tID           int         `json:\"id\"`\n\tModifiedDate time.Time   `json:\"modified_date\"`\n\tName         string      `json:\"name\"`\n\tOrder        int         `json:\"order\"`\n\tProject      int         `json:\"project\"`\n\tType         string      `json:\"type\"`\n}\n```\n\nThen initialise an instance which is going to store the response:\n```go\nepicCustomAttributes := []EpicCustomAttributeDetail{}\n```\n\nUsing `client.MakeURL` the absolute URL endpoint is built for the request. \u003cbr\u003e\nUsing `client.Request.Get` an HTTP GET request is sent to the API endpoint URL. \u003cbr\u003e\nThe `client.Request.Get` call must receive a URL and a pointer to the model struct:\n```go\n// Final URL should be https://api.taiga.io/api/v1/epic-custom-attributes\nresp, err := client.Request.Get(client.MakeURL(\"epic-custom-attributes\"), \u0026epicCustomAttributes)\nif err != nil {\n\tfmt.Println(err)\n\tfmt.Println(resp)\n} else {\n\tfmt.Println(\"The following Epic Custom Attributes have been returned:\")\n\tfmt.Println(\"--------------------------------------------------------\")\n\tfor i := 0; i \u003c 3; i++ {\n\t\tca := epicCustomAttributes[i]\n\t\tfmt.Println(\"  * \", ca.ID, ca.Name)\n\t}\n}\n```\n\n**Note:** Such raw requests return `(*http.Response, error)`.\n\n### \\\u003cTaiga Object\\\u003e Custom Attributes\nThe custom attribute of various Taiga objects are made of two major corner stones:\n  - Field Definitions\n  - Field Values\n\n**Field Definitions** internally connect a field's name to an ID (int). \u003cbr\u003e\nRequesting `http://localhost:8000/api/v1/epic-custom-attributes/14` results in something like this:\n```json\n{\n    \"created_date\": \"2020-07-02T11:57:22.124Z\",\n    \"description\": \"nesciunt consectetur culpa ullam harum fugit veritatis eius dolorem assumenda\",\n    \"extra\": null,\n    \"id\": 14,\n    \"modified_date\": \"2020-07-03T08:40:34.667Z\",\n    \"name\": \"Duration 1\",\n    \"order\": 1,\n    \"project\": 3,\n    \"type\": \"url\"\n}\n```\n\n**Field Values** internally connect the user-provided unique values to the internal IDs. \u003cbr\u003e\nRequesting `http://localhost:8000/api/v1/epics/custom-attributes-values/15` results in something like this:\n```json\n{\n    \"attributes_values\": {\n        \"14\": \"240 min\"\n    },\n    \"epic\": 15,\n    \"version\": 2\n}\n```\nObserve that `Duration 1` has ID `14` in the declaration and that's used as the field's name.\n\nIf you request the custom field values of a Taiga object, the values will be returned in a `map[string]interface{}` style by default.\n\nYou have the option to manually declare the expected custom attribute fields and types in advance, and use\nyour custom struct for serializing the returned values.\n\nFor example here's the custom epic custom attribute struct for Taigo's Sandbox Project:\n```go\nimport (\n\ttaiga \"github.com/theriverman/taigo\"\n)\n\ntype TaigoSandboxEpicCustomAttributeFields struct {\n\tSupportTeamName       string `json:\"9216\"`\n\tEstimatedDeliveryDate string `json:\"9217\"`\n\tCostUSD               int    `json:\"9218\"`\n}\ntype TaigoSandboxEpicCustomAttribValues struct {\n\ttaiga.EpicCustomAttributeValues\n\tAttributesValues TaigoSandboxEpicCustomAttributeFields `json:\"attributes_values,omitempty\"`\n}\n```\n\nObserve how the custom `TaigoSandboxEpicCustomAttributeFields` is promoted in the custom `TaigoSandboxEpicCustomAttribValues` struct.\n\nAll that's left is to create an instance of `TaigoSandboxEpicCustomAttribValues` and use it to serialze the returned JSON:\n```go\ncavs := TaigoSandboxEpicCustomAttribValues{} // Custom Attribute Value(s)\nresp, err := client.Request.Get(client.MakeURL(\"epics\", \"custom-attributes-values\", strconv.Itoa(\"your-epics-id\")), \u0026cavs)\nif err != nil {\n\tlog.Println(err)\n\tlog.Println(resp)\n\treturn\n}\n```\n\n# Logging \u0026 Verbose Mode\n## Logging\n\n## Verbose Mode\nVerbose mode can be enabled by setting the `Verbose` field to `true` in `taiga.Client`. For example:\n```go\nclient := taiga.Client{\n\tVerbose:    true\n}\n```\n\n# Contribution\nYou're contribution would be much appreciated! \u003cbr\u003e\nFeel free to open Issue tickets or create Pull requests. \u003cbr\u003e\n\nShould you have an idea which would cause non-backward compatibility, please open an issue first to discuss your proposal!\n\nFor more details, see [TAIGO Contribution](CONTRIBUTION.md).\n\n## Branching Strategy\n  * **master** is \u003ci\u003ealways\u003c/i\u003e stable\n  * **develop** is *not* \u003ci\u003ealways\u003c/i\u003e stable\n  * **feature_\\*** branches are used for introducing larger changes\n\n# Licenses \u0026 Recognitions\n| Product\t\t\t\t\t| License\t| Author\t\t\t\t\t\t\t\t\t\t\t\t\t|\n|---------------------------|-----------|-----------------------------------------------------------|\n| **Go Gopher**             | CC3.0     | [Renee French](https://www.instagram.com/reneefrench/) \t|\n| **Gopher Konstructor**    | CC0-1.0   | [quasilyte](https://github.com/quasilyte/gopherkon)    \t|\n| **TAIGA**                 | AGPL-3.0  | [Taiga.io](https://github.com/taigaio)                 \t|\n| **Taigo**                 | MIT       | [theriverman](https://github.com/theriverman)          \t|\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheriverman%2Ftaigo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheriverman%2Ftaigo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheriverman%2Ftaigo/lists"}