# API Documentation

## Bearer Token & API Key Generation

**Bearer authentication** (also called **token authentication**) is an HTTP **authentication** scheme that involves security **tokens** called **bearer tokens**. GoGovSG uses bearer authentication.&#x20;

To generate the token, click on "API Integration" in the navigation bar. From there, click on `Generate API key` and copy the token. Use this key to start using GoGovSG's API.&#x20;

<figure><img src="https://3066292128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWvkdW0u1RBIeooYvKH%2Fuploads%2F6BmwkKuWpZOc8qT4MX92%2FScreenshot%202022-11-24%20at%205.29.13%20PM.png?alt=media&#x26;token=f41c9136-4da1-4f24-9c40-b9d4bd1c7b98" alt=""><figcaption></figcaption></figure>

<figure><img src="https://3066292128-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MWvkdW0u1RBIeooYvKH%2Fuploads%2Fz9AndRHYSYdk9H3fWWDh%2FScreenshot%202022-11-24%20at%205.30.21%20PM.png?alt=media&#x26;token=c7019503-7356-4f16-b772-6ad565c65705" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
**Keep the bearer token** **safe:** You should not share the bearer token with anyone. Use services like 1Password to store it.&#x20;
{% endhint %}

## Authentication

GoGovSG's API uses APIKey for authentication. User can view and manage API Keys in Go API Dashboard.

Staging secret keys will have `test_v1_`version prefix.

Production secret keys will have `live_v1_`version prefix.

Authentication to the API is performed via bearer auth.

```powershell
curl --location --request POST 'https://go.gov.sg/api/v1/urls' \
--header 'Authorization: Bearer live_v1_YOUR_API_KEY'
```

All API requests must be made over HTTPS. Calls made over plain HTTP will fail and requests without authentication will also fail.

## Errors

Go API uses conventional API Error to indicate the success or failure of an API request.

| Status Codes                       | Description                                                                                      |
| ---------------------------------- | ------------------------------------------------------------------------------------------------ |
| 200 - OK                           | Everything worked as expected.                                                                   |
| 400 - Bad Request                  | The request was unacceptable, often due to missing a required parameter.                         |
| 401 - Unauthorized                 | No valid API key provided.                                                                       |
| 402 - Request Failed               | The parameters were valid but the request failed.                                                |
| 404 - Not Found                    | The requested resource doesn't exist.                                                            |
| 429 - Too Many Requests            | Too many requests hit the API too quickly. We recommend an exponential backoff of your requests. |
| 500, 502, 503, 504 - Server Errors | Something went wrong on GoGovSG's API end.                                                       |

```json
{
  "message": "Unauthorized"
}
```

## Rate Limits

GoGovSG supports a default rate limit of 5 requests per second for each user. If you require higher rate limits, please write to us at <go@open.gov.sg> with more details.

If you have exceeded your rate limit, your incoming requests will be blocked for 10 seconds as a cooling off period. We recommend throttling your requests and implementing exponential backoff for retries to ensure that your requests can be accepted.

## Endpoints

| Environment | Endpoint                                                     |
| ----------- | ------------------------------------------------------------ |
| Production  | [https://go.gov.sg/api/](https://go.gov.sg/)                 |
| Staging     | [https://staging.go.gov.sg/api/](https://staging.go.gov.sg/) |

## Get Urls

```jsx
GET /v1/urls?...
```

**Request Query Parameters:**

<table><thead><tr><th>Parameter</th><th width="201.33333333333331">Type</th><th>Default value</th><th>Required?</th></tr></thead><tbody><tr><td><code>limit</code></td><td>number</td><td>1000</td><td>No, optional</td></tr><tr><td><code>offset</code></td><td>number</td><td>0</td><td>No, optional</td></tr><tr><td><code>searchText</code></td><td>string</td><td>nil</td><td>No, optional</td></tr><tr><td><code>state</code></td><td>enum (”ACTIVE”, “INACTIVE”)</td><td>nil</td><td>No, optional</td></tr><tr><td><code>orderBy</code></td><td>enum (”createdAt”, “clicks”)</td><td>createdAt</td><td>No, optional</td></tr><tr><td><code>sortDirection</code></td><td>enum (”desc”, “asc”)</td><td>desc</td><td>No, optional</td></tr><tr><td><code>isFile</code></td><td>boolean</td><td>nil</td><td>No, optional</td></tr></tbody></table>

Note: Max values for `limit` = 1000

**Returns**:

```json
{
  "urls": [
    {
      "shortUrl": "197abc",
      "longUrl": "https://link.com",
      "state": "ACTIVE",
      "clicks": 0,
      "createdAt": "2022-09-19T03:31:00.131Z",
      "updatedAt": "2022-09-19T03:31:00.131Z"
    }
  ],
  "count": 1
}
```

**Explanation of fields returned:**

<table><thead><tr><th width="173">Field Returned</th><th width="256">What it means</th><th>Example</th></tr></thead><tbody><tr><td><code>shortUrl</code></td><td>Short link name</td><td>agsubmit <br><br>(ie. full URL will look like https://go.gov.sg/agsubmit)</td></tr><tr><td><code>longUrl</code></td><td>Original link</td><td>https://google.com</td></tr><tr><td><code>state</code></td><td>Whether short link is active or inactive</td><td>"ACTIVE" or "INACTIVE"</td></tr><tr><td><code>clicks</code></td><td>Number of clicks on the short link since creation</td><td>888</td></tr><tr><td><code>count</code></td><td>Counts the total number of links matching search filters (except <code>limit</code> and <code>offset</code>) </td><td>8</td></tr></tbody></table>

## Create Url

```jsx
POST /v1/urls
```

**Request body:**

| Property | Type   | Required?     |
| -------- | ------ | ------------- |
| longUrl  | string | Yes, required |
| shortUrl | string | No, optional  |

* &#x20;`longUrl` has to start with https\://
* If no `shortUrl` is provided, then a random 8 character alphanumeric shortUrl name will be generated for the link.

**Returns**:

```json
{
  "shortUrl": "197abc",
  "longUrl": "https://link.com",
  "state": "ACTIVE",
  "clicks": 0,
  "createdAt": "2022-09-19T03:31:00.131Z",
  "updatedAt": "2022-09-19T03:31:00.131Z"
}
```

```json
{
  "message": "Short link \\"asd\\" is already used.",
  "type": "ShortUrlError"
}
```

## Update Url

```jsx
PATCH /v1/urls/{shortUrl}
```

Note: Indicate `shortUrl` name you wish to update in above PATCH request, ie. {shortUrl}

**Request body:**

<table><thead><tr><th>Property</th><th width="278.3333333333333">Type</th><th>Required?</th></tr></thead><tbody><tr><td><code>longUrl</code></td><td>string</td><td>No, optional</td></tr><tr><td><code>state</code></td><td>enum (”ACTIVE”, “INACTIVE”)</td><td>No, optional</td></tr></tbody></table>

* `longUrl` has to start with https\://

**Returns**:

```jsx
{
  "shortUrl": "197abc",
  "longUrl": "https://link.com",
  "state": "ACTIVE",
  "clicks": 0,
  "createdAt": "2022-09-19T03:31:00.131Z",
  "updatedAt": "2022-09-19T03:31:00.131Z"
}
```
