curl --request POST \
--url https://app.ohmyho.st/v1/projects \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"organization_id": "<string>",
"name": "<string>",
"data_mode": "shared"
}
'import requests
url = "https://app.ohmyho.st/v1/projects"
payload = {
"organization_id": "<string>",
"name": "<string>",
"data_mode": "shared"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({organization_id: '<string>', name: '<string>', data_mode: 'shared'})
};
fetch('https://app.ohmyho.st/v1/projects', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.ohmyho.st/v1/projects",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'organization_id' => '<string>',
'name' => '<string>',
'data_mode' => 'shared'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.ohmyho.st/v1/projects"
payload := strings.NewReader("{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.ohmyho.st/v1/projects")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.ohmyho.st/v1/projects")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"state": "queued",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"result": {},
"error": {
"code": "operation_failed",
"message": "<string>",
"retryable": false,
"suggested_action": "<string>"
},
"progress": {
"phase": "queued",
"project_id": "<string>",
"deployment_id": "<string>",
"observed_at": "2023-11-07T05:31:56Z",
"next_poll_after_seconds": 60,
"suggested_action": "<string>",
"build_completed_at": "2023-11-07T05:31:56Z"
},
"reconciliation": {
"state": "required",
"attempt_id": "<string>",
"observed_at": "2023-11-07T05:31:56Z",
"suggested_action": "<string>"
}
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "https://docs.ohmyho.st/errors/idempotency-key-reused",
"title": "Idempotency key reused",
"status": 409,
"code": "idempotency_key_reused",
"request_id": "req_01J00000000000000000000000",
"retryable": false,
"suggested_action": "Retry with a new idempotency key."
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}Create a project
Atomically records the project and a durable operation for asynchronous processing.
curl --request POST \
--url https://app.ohmyho.st/v1/projects \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: <idempotency-key>' \
--data '
{
"organization_id": "<string>",
"name": "<string>",
"data_mode": "shared"
}
'import requests
url = "https://app.ohmyho.st/v1/projects"
payload = {
"organization_id": "<string>",
"name": "<string>",
"data_mode": "shared"
}
headers = {
"Idempotency-Key": "<idempotency-key>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'Idempotency-Key': '<idempotency-key>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({organization_id: '<string>', name: '<string>', data_mode: 'shared'})
};
fetch('https://app.ohmyho.st/v1/projects', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://app.ohmyho.st/v1/projects",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'organization_id' => '<string>',
'name' => '<string>',
'data_mode' => 'shared'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"Idempotency-Key: <idempotency-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://app.ohmyho.st/v1/projects"
payload := strings.NewReader("{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Idempotency-Key", "<idempotency-key>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://app.ohmyho.st/v1/projects")
.header("Idempotency-Key", "<idempotency-key>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.ohmyho.st/v1/projects")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Idempotency-Key"] = '<idempotency-key>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"organization_id\": \"<string>\",\n \"name\": \"<string>\",\n \"data_mode\": \"shared\"\n}"
response = http.request(request)
puts response.read_body{
"id": "<string>",
"state": "queued",
"created_at": "2023-11-07T05:31:56Z",
"updated_at": "2023-11-07T05:31:56Z",
"result": {},
"error": {
"code": "operation_failed",
"message": "<string>",
"retryable": false,
"suggested_action": "<string>"
},
"progress": {
"phase": "queued",
"project_id": "<string>",
"deployment_id": "<string>",
"observed_at": "2023-11-07T05:31:56Z",
"next_poll_after_seconds": 60,
"suggested_action": "<string>",
"build_completed_at": "2023-11-07T05:31:56Z"
},
"reconciliation": {
"state": "required",
"attempt_id": "<string>",
"observed_at": "2023-11-07T05:31:56Z",
"suggested_action": "<string>"
}
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "https://docs.ohmyho.st/errors/idempotency-key-reused",
"title": "Idempotency key reused",
"status": 409,
"code": "idempotency_key_reused",
"request_id": "req_01J00000000000000000000000",
"retryable": false,
"suggested_action": "Retry with a new idempotency key."
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}{
"type": "<string>",
"title": "<string>",
"status": 499,
"code": "invalid_request",
"request_id": "<string>",
"retryable": true,
"suggested_action": "<string>",
"detail": "<string>",
"instance": "<string>",
"retry_after_seconds": 43200
}Authorizations
WorkOS access JWT or a user-owned WorkOS API key. User keys are bound to one organization and restricted to their enabled product permissions. Session-only onboarding and session revocation require an interactive access JWT. No cookie session is assumed.
Headers
Optional caller-provided correlation identifier.
1 - 128Identifies one mutation and its canonical request payload.
1 - 128Body
Phase 1 project creation request. The server assigns resource identifiers.
^[0-9A-HJKMNP-TV-Z]{26}$1 - 128^\S(?:.*\S)?$Chosen when the project is created. shared uses one database and a shared file namespace across Dev/Prod; isolated keeps their database/Auth records and files separate. Skills recommend isolated development, but the customer chooses the additional measured database consumption. Promotion applies pending schema migrations to an isolated Prod database without copying Dev data. Changing an established mode requires an explicit data migration.
shared, isolated Response
The mutation was accepted for asynchronous processing.
Durable record returned for an accepted asynchronous mutation. Optional reconciliation is a current observation for queued/running work, separate from immutable terminal state. A completed reconciliation attempt alone does not mean the operation succeeded.
^[0-9A-HJKMNP-TV-Z]{26}$queued, running, succeeded, failed, cancelled Show child attributes
Show child attributes
Current deployment dependency observation, separate from immutable operation history. Poll the same operation; mail readiness does not mean application activation.
Show child attributes
Show child attributes
Show child attributes
Show child attributes