{"id":15192173,"url":"https://github.com/richardknop/example-api","last_synced_at":"2025-10-27T17:30:25.862Z","repository":{"id":57506626,"uuid":"49883789","full_name":"RichardKnop/example-api","owner":"RichardKnop","description":"A base API project to bootstrap and prototype quickly.","archived":false,"fork":false,"pushed_at":"2018-05-26T09:27:13.000Z","size":28570,"stargazers_count":27,"open_issues_count":0,"forks_count":9,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-09-27T21:05:33.558Z","etag":null,"topics":["docker","docker-compose","etcd","go","golang","postgres","prototype"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mpl-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RichardKnop.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":"2016-01-18T14:56:06.000Z","updated_at":"2023-03-10T18:15:23.000Z","dependencies_parsed_at":"2022-08-29T20:01:22.420Z","dependency_job_id":null,"html_url":"https://github.com/RichardKnop/example-api","commit_stats":null,"previous_names":["richardknop/recall"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RichardKnop%2Fexample-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RichardKnop%2Fexample-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RichardKnop%2Fexample-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RichardKnop%2Fexample-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RichardKnop","download_url":"https://codeload.github.com/RichardKnop/example-api/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219875658,"owners_count":16554696,"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":["docker","docker-compose","etcd","go","golang","postgres","prototype"],"created_at":"2024-09-27T21:05:52.173Z","updated_at":"2025-10-27T17:30:17.629Z","avatar_url":"https://github.com/RichardKnop.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Example API\n\nThis is a base project to bootstrap and prototype quickly. It is useful as a starting point for REST APIs and includes full OAuth 2.0 implementation as well as basic endpoints to create and update a user, health check endpoint, Facebook integration, migrations and a ready to rumble Dockerfile.\n\nIt relies on `Postgres` for database and `etcd` for configuration but both are easily customizable. An [ORM library](https://github.com/jinzhu/gorm) is used for database communication.\n\n[![Travis Status for RichardKnop/example-api](https://travis-ci.org/RichardKnop/example-api.svg?branch=master\u0026label=linux+build)](https://travis-ci.org/RichardKnop/example-api)\n[![godoc for RichardKnop/example-api](https://godoc.org/github.com/nathany/looper?status.svg)](http://godoc.org/github.com/RichardKnop/example-api)\n[![codecov for RichardKnop/example-api](https://codecov.io/gh/RichardKnop/example-api/branch/master/graph/badge.svg)](https://codecov.io/gh/RichardKnop/example-api)\n\n---\n\n* [API Design](#api-design)\n* [API Docs](../../../example-api/blob/master/docs/)\n* [Dependencies](#dependencies)\n* [Setup](#setup)\n* [Test Data](#test-data)\n* [Testing](#testing)\n* [Docker](#docker)\n* [Docker Compose](#docker-compose)\n\n## API Design\n\nThe API is using REST architectural style which means resources are access and modified via HTTP methods:\n\n- `GET` (to get a resource or paginate over resource sets)\n- `POST` (to create new resources)\n- `PUT` (to update resources)\n- `DELETE` (to delete resources)\n\n`PATCH` might be implemented later in order to enable partial updates of resources (see the [RFC](https://tools.ietf.org/html/rfc7396)).\n\nThe REST API objects are formatted according to JSON [HAL](http://stateless.co/hal_specification.html) specification. This means that each object has its own hyperlink clients can use to access it. Other related objects can be embedded into the response as well.\n\nSimple example of JSON HAL resource:\n\n```json\n{\n  \"_links\": {\n    \"self\": {\n      \"href\": \"/v1/users/1\"\n    }\n  },\n  \"id\": 1,\n  \"email\": \"john@reese\",\n  \"created_at\": \"2015-12-17T06:17:54Z\",\n  \"updated_at\": \"2015-12-17T06:17:54Z\"\n}\n```\n\nLet's take a look at how a related object would be represented. The example bellow shows a file resource with embedded user object.\n\n```json\n{\n  \"_links\": {\n    \"self\": {\n      \"href\":\"/v1/files/1\"\n    }\n  },\n  \"_embedded\": {\n    \"user\": {\n      \"_links\": {\n        \"self\": {\n          \"href\":\"/v1/users/1\"\n        }\n      },\n      \"id\":1\n    }\n  },\n  \"id\":1,\n  \"user_id\":1\n}\n```\n\nPagination example:\n\n```json\n{\n  \"_links\":{\n    \"first\":{\n      \"href\":\"/v1/files?page=1\"\n    },\n    \"last\":{\n      \"href\":\"/v1/files?page=2\"\n    },\n    \"next\":{\n      \"href\":\"/v1/files?page=2\"\n    },\n    \"prev\":{\n      \"href\":\"\"\n    },\n    \"self\":{\n      \"href\":\"/v1/files?page=1\"\n    }\n  },\n  \"_embedded\":{\n    \"files\":[\n      {\n        \"_links\":{\n          \"self\":{\n            \"href\":\"/v1/files/1\"\n          }\n        },\n        \"id\":1\n      },\n      {\n        \"_links\":{\n          \"self\":{\n            \"href\":\"/v1/files/2\"\n          }\n        },\n        \"id\":2\n      }\n    ]\n  },\n  \"count\":2,\n  \"page\":1\n}\n```\n\n## Dependencies\n\nAccording to [Go 1.5 Vendor experiment](https://docs.google.com/document/d/1Bz5-UB7g2uPBdOx-rw5t9MxJwkfpx90cqG9AFL0JAYo), all dependencies are stored in the vendor directory. This approach is called `vendoring` and is the best practice for Go projects to lock versions of dependencies in order to achieve reproducible builds.\n\nThis project uses [dep](https://github.com/golang/dep) for dependency management. To update dependencies during development:\n\n```sh\ndep ensure\n```\n\n## Setup\n\nIf you are developing on OSX, install `etcd` and `Postgres`:\n\n### etcd\n\n```sh\nbrew install etcd\n```\n\nLoad a development configuration into `etcd`:\n\n```sh\netcdctl put /config/example_api.json '{\n  \"Database\": {\n    \"Type\": \"postgres\",\n    \"Host\": \"localhost\",\n    \"Port\": 5432,\n    \"User\": \"example_api\",\n    \"Password\": \"\",\n    \"DatabaseName\": \"example_api\",\n    \"MaxIdleConns\": 5,\n    \"MaxOpenConns\": 5\n  },\n  \"Oauth\": {\n    \"AccessTokenLifetime\": 3600,\n    \"RefreshTokenLifetime\": 1209600,\n    \"AuthCodeLifetime\": 3600\n  },\n  \"Mailgun\": {\n    \"Domain\": \"example.com\",\n    \"APIKey\": \"mailgun_api_key\",\n    \"PublicAPIKey\": \"mailgun_private_api_key\"\n  },\n  \"Web\": {\n    \"Scheme\": \"http\",\n    \"Host\": \"localhost:8080\",\n    \"AppScheme\": \"http\",\n    \"AppHost\": \"localhost:8000\"\n  },\n  \"AppSpecific\": {\n    \"ConfirmationLifetime\": 604800,\n    \"InvitationLifetime\": 604800,\n    \"PasswordResetLifetime\": 604800,\n    \"CompanyName\": \"Example Ltd\",\n    \"CompanyNoreplyEmail\": \"noreply@example.com\",\n    \"ConfirmationURLFormat\": \"%s://%s/confirm-email/%s\",\n    \"InvitationURLFormat\": \"%s://%s/confirm-invitation/%s\",\n    \"PasswordResetURLFormat\": \"%s://%s/reset-password/%s\"\n  },\n  \"IsDevelopment\": true\n}'\n```\n\nCheck the config was loaded properly:\n\n```sh\netcdctl get /config/example_api.json\n```\n\n### Postgres\n\n```sh\nbrew install postgres\n```\n\nYou might want to create a `Postgres` database:\n\n```sh\ncreateuser --createdb example_api\ncreatedb -U example_api example_api\n```\n\n### Compile \u0026 Run\n\nCompile the app:\n\n```sh\ngo install .\n```\n\nRun migrations:\n\n```sh\nexample-api migrate\n```\n\nAnd finally, run the app:\n\n```sh\nexample-api runserver\n```\n\nWhen deploying, you can set etcd related environment variables:\n\n* `ETCD_ENDPOINTS`\n* `ETCD_CERT_FILE`\n* `ETCD_KEY_FILE`\n* `ETCD_CA_FILE`\n* `ETCD_CONFIG_PATH`\n\n## Test Data\n\nYou might want to insert some test data if you are testing locally using `curl` examples from this README:\n\n```sh\nexample-api loaddata \\\n  services/oauth/fixtures/scopes.yml \\\n  services/oauth/fixtures/roles.yml \\\n  services/oauth/fixtures/test_clients.yml \\\n  services/oauth/fixtures/test_users.yml \\\n  services/accounts/fixtures/test_users.yml\n```\n\n## Testing\n\nI have used a mix of unit and functional tests so you need to have `sqlite` installed in order for the tests to run successfully as the suite creates an in-memory database.\n\nTo run tests:\n\n```sh\nmake test\n```\n\n## Docker\n\nBuild a Docker image and run the app in a container:\n\n```sh\ndocker build -t example-api:latest .\ndocker run -e ETCD_ENDPOINTs=localhost:2379 -p 8080:8080 --name example-api example-api:latest\n```\n\nYou can load fixtures with `docker exec` command:\n\n```sh\ndocker exec \u003ccontainer_id\u003e /go/bin/example-api loaddata \\\n  services/oauth/fixtures/scopes.yml \\\n  services/oauth/fixtures/roles.yml \\\n  services/oauth/fixtures/test_clients.yml\n```\n\nYou can also execute interactive commands by passing `-i` flag:\n\n```sh\ndocker exec -i \u003ccontainer_id\u003e /go/bin/example-api createoauthclient\ndocker exec -i \u003ccontainer_id\u003e /go/bin/example-api createsuperuser\n```\n\n## Docker Compose\n\nYou can use [docker-compose](https://docs.docker.com/compose/) to start the app, postgres, etcd in separate linked containers:\n\n```sh\ndocker-compose up\n```\n\nDuring `docker-compose up` process all configuration and fixtures will be loaded. After successful up you can check, that app is running using for example the health check request:\n\n```sh\ncurl --compressed -v localhost:8080/v1/health\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardknop%2Fexample-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichardknop%2Fexample-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardknop%2Fexample-api/lists"}