MENU navbar-image

Introduction

This documentation aims to provide all the information you need to work with our API.

<aside>As you scroll, you'll see code examples for working with the API in different programming languages in the dark area to the right (or as part of the content on mobile).
You can switch the language used with the tabs at the top right (or from the nav menu at the top left on mobile).</aside>

Authenticating requests

This API is not authenticated.

Endpoints

GET api/user

Example request:
curl --request GET \
    --get "https://forge.test/api/user" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/user"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/user

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

POST api/webhooks/github

Example request:
curl --request POST \
    "https://forge.test/api/webhooks/github" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/webhooks/github"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/webhooks/github

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

POST api/v1/tickets

Example request:
curl --request POST \
    "https://forge.test/api/v1/tickets" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "summary=b"\
    --form "description=Et animi quos velit et fugiat."\
    --form "service_product_id=architecto"\
    --form "email=zbailey@example.net"\
    --form "player_id=i"\
    --form "build=y"\
    --form "platform=v"\
    --form "severity=minor"\
    --form "attachments[]=@/private/var/folders/48/zstrqz0d3cb36v0r9cdnbh7c0000gn/T/phpylPExO" 
const url = new URL(
    "https://forge.test/api/v1/tickets"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('summary', 'b');
body.append('description', 'Et animi quos velit et fugiat.');
body.append('service_product_id', 'architecto');
body.append('email', 'zbailey@example.net');
body.append('player_id', 'i');
body.append('build', 'y');
body.append('platform', 'v');
body.append('severity', 'minor');
body.append('attachments[]', document.querySelector('input[name="attachments[]"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Request      

POST api/v1/tickets

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

Body Parameters

summary   string   

Must be at least 4 characters. Must not be greater than 200 characters. Example: b

description   string   

Must be at least 10 characters. Must not be greater than 8000 characters. Example: Et animi quos velit et fugiat.

service_product_id   string   

The id of an existing record in the service_products table. Example: architecto

email   string  optional  

Must be a valid email address. Must not be greater than 255 characters. Example: zbailey@example.net

player_id   string  optional  

Must not be greater than 255 characters. Example: i

build   string  optional  

Must not be greater than 64 characters. Example: y

platform   string  optional  

Must not be greater than 32 characters. Example: v

severity   string  optional  

Example: minor

Must be one of:
  • trivial
  • minor
  • major
  • critical
metadata   object  optional  
attachments   file[]  optional  

Must be a file. Must not be greater than 10240 kilobytes.

GET api/v1/me

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/me" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/me"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/me

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

GET api/v1/projects

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/projects" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/projects"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/projects

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

GET api/v1/projects/{id}

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/projects/6dbe929c-6f1f-47df-bc3c-b4ea3d0d55f6" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/projects/6dbe929c-6f1f-47df-bc3c-b4ea3d0d55f6"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/projects/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the project. Example: 6dbe929c-6f1f-47df-bc3c-b4ea3d0d55f6

GET api/v1/lookups

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/lookups" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/lookups"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/lookups

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

GET api/v1/issues

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/issues" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/issues"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/issues

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

POST api/v1/issues

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"project_id\": \"6ff8f7f6-1eb3-3525-be4a-3932c805afed\",
    \"summary\": \"g\",
    \"description\": \"Eius et animi quos velit et.\",
    \"issue_type_id\": 16,
    \"issue_priority_id\": 16,
    \"issue_status_id\": 16,
    \"assignee_id\": \"a4855dc5-0acb-33c3-b921-f4291f719ca0\",
    \"parent_id\": \"c90237e9-ced5-3af6-88ea-84aeaa148878\",
    \"tags\": [
        \"architecto\"
    ]
}"
const url = new URL(
    "https://forge.test/api/v1/issues"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "project_id": "6ff8f7f6-1eb3-3525-be4a-3932c805afed",
    "summary": "g",
    "description": "Eius et animi quos velit et.",
    "issue_type_id": 16,
    "issue_priority_id": 16,
    "issue_status_id": 16,
    "assignee_id": "a4855dc5-0acb-33c3-b921-f4291f719ca0",
    "parent_id": "c90237e9-ced5-3af6-88ea-84aeaa148878",
    "tags": [
        "architecto"
    ]
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/v1/issues

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

Body Parameters

project_id   string   

Must be a valid UUID. The id of an existing record in the projects table. Example: 6ff8f7f6-1eb3-3525-be4a-3932c805afed

summary   string   

Must not be greater than 255 characters. Example: g

description   string  optional  

Example: Eius et animi quos velit et.

issue_type_id   integer   

The id of an existing record in the issue_types table. Example: 16

issue_priority_id   integer  optional  

The id of an existing record in the issue_priorities table. Example: 16

issue_status_id   integer  optional  

The id of an existing record in the issue_statuses table. Example: 16

assignee_id   string  optional  

Must be a valid UUID. The id of an existing record in the users table. Example: a4855dc5-0acb-33c3-b921-f4291f719ca0

parent_id   string  optional  

Must be a valid UUID. The id of an existing record in the issues table. Example: c90237e9-ced5-3af6-88ea-84aeaa148878

tags   string[]  optional  

GET api/v1/issues/{id}

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/issues/OMP-1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/issues/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the issue. Example: OMP-1

PUT api/v1/issues/{id}

Example request:
curl --request PUT \
    "https://forge.test/api/v1/issues/OMP-1" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"summary\": \"b\",
    \"description\": \"Eius et animi quos velit et.\",
    \"issue_type_id\": 16,
    \"issue_priority_id\": 16,
    \"issue_status_id\": 16,
    \"assignee_id\": \"a4855dc5-0acb-33c3-b921-f4291f719ca0\",
    \"parent_id\": \"c90237e9-ced5-3af6-88ea-84aeaa148878\",
    \"tags\": [
        \"architecto\"
    ]
}"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "summary": "b",
    "description": "Eius et animi quos velit et.",
    "issue_type_id": 16,
    "issue_priority_id": 16,
    "issue_status_id": 16,
    "assignee_id": "a4855dc5-0acb-33c3-b921-f4291f719ca0",
    "parent_id": "c90237e9-ced5-3af6-88ea-84aeaa148878",
    "tags": [
        "architecto"
    ]
};

fetch(url, {
    method: "PUT",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

PUT api/v1/issues/{id}

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

id   string   

The ID of the issue. Example: OMP-1

Body Parameters

summary   string  optional  

Must not be greater than 255 characters. Example: b

description   string  optional  

Example: Eius et animi quos velit et.

issue_type_id   integer  optional  

The id of an existing record in the issue_types table. Example: 16

issue_priority_id   integer  optional  

The id of an existing record in the issue_priorities table. Example: 16

issue_status_id   integer  optional  

The id of an existing record in the issue_statuses table. Example: 16

assignee_id   string  optional  

Must be a valid UUID. The id of an existing record in the users table. Example: a4855dc5-0acb-33c3-b921-f4291f719ca0

parent_id   string  optional  

Must be a valid UUID. The id of an existing record in the issues table. Example: c90237e9-ced5-3af6-88ea-84aeaa148878

tags   string[]  optional  

POST api/v1/issues/{issue_id}/transition

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/transition" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"to_status_id\": 16
}"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/transition"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "to_status_id": 16
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/transition

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

Body Parameters

to_status_id   integer   

The id of an existing record in the issue_statuses table. Example: 16

POST api/v1/issues/{issue_id}/comments

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/comments" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"body\": \"b\"
}"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/comments"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "body": "b"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/comments

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

Body Parameters

body   string   

Must not be greater than 65000 characters. Example: b

POST api/v1/issues/{issue_id}/attachments

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/attachments" \
    --header "Content-Type: multipart/form-data" \
    --header "Accept: application/json" \
    --form "file=@/private/var/folders/48/zstrqz0d3cb36v0r9cdnbh7c0000gn/T/phpo6yYCq" 
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/attachments"
);

const headers = {
    "Content-Type": "multipart/form-data",
    "Accept": "application/json",
};

const body = new FormData();
body.append('file', document.querySelector('input[name="file"]').files[0]);

fetch(url, {
    method: "POST",
    headers,
    body,
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/attachments

Headers

Content-Type      

Example: multipart/form-data

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

Body Parameters

file   file   

Must be a file. Must not be greater than 10240 kilobytes. Example: /private/var/folders/48/zstrqz0d3cb36v0r9cdnbh7c0000gn/T/phpo6yYCq

GET /api/v1/issues/{issue:id}/time/summary

Example request:
curl --request GET \
    --get "https://forge.test/api/v1/issues/OMP-1/time/summary" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/time/summary"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "GET",
    headers,
}).then(response => response.json());

Example response (401):

Show headers
cache-control: no-cache, private
content-type: application/json
access-control-allow-origin: *
 

{
    "message": "Unauthenticated."
}
 

Request      

GET api/v1/issues/{issue_id}/time/summary

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

POST /api/v1/issues/{issue:id}/time/start Starts a running timer for the authenticated user.

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/time/start" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/time/start"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/time/start

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

POST /api/v1/issues/{issue:id}/time/stop Stops the current running timer for the authenticated user.

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/time/stop" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/time/stop"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

fetch(url, {
    method: "POST",
    headers,
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/time/stop

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

POST /api/v1/issues/{issue:id}/time Manual log: accepts either {seconds} or {started_at, ended_at}, plus optional note.

Example request:
curl --request POST \
    "https://forge.test/api/v1/issues/OMP-1/time" \
    --header "Content-Type: application/json" \
    --header "Accept: application/json" \
    --data "{
    \"started_at\": \"2025-09-19T15:54:45\",
    \"ended_at\": \"2051-10-13\",
    \"note\": \"n\"
}"
const url = new URL(
    "https://forge.test/api/v1/issues/OMP-1/time"
);

const headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
};

let body = {
    "started_at": "2025-09-19T15:54:45",
    "ended_at": "2051-10-13",
    "note": "n"
};

fetch(url, {
    method: "POST",
    headers,
    body: JSON.stringify(body),
}).then(response => response.json());

Request      

POST api/v1/issues/{issue_id}/time

Headers

Content-Type      

Example: application/json

Accept      

Example: application/json

URL Parameters

issue_id   string   

The ID of the issue. Example: OMP-1

Body Parameters

started_at   string   

Must be a valid date. Example: 2025-09-19T15:54:45

ended_at   string   

Must be a valid date. Must be a date after started_at. Example: 2051-10-13

note   string  optional  

Must not be greater than 2000 characters. Example: n