curl --request POST \
--url https://app.ohmyho.st/v1/projects/{project_id}/database/access \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "read",
"ttl_seconds": 3600,
"label": "<string>"
}
'import requests
url = "https://app.ohmyho.st/v1/projects/{project_id}/database/access"
payload = {
"mode": "read",
"ttl_seconds": 3600,
"label": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'read', ttl_seconds: 3600, label: '<string>'})
};
fetch('https://app.ohmyho.st/v1/projects/{project_id}/database/access', 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/{project_id}/database/access",
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([
'mode' => 'read',
'ttl_seconds' => 3600,
'label' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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/{project_id}/database/access"
payload := strings.NewReader("{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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/{project_id}/database/access")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.ohmyho.st/v1/projects/{project_id}/database/access")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"access_id": "<string>",
"environment": "dev",
"mode": "read",
"role_name": "<string>",
"host": "<string>",
"database": "neondb",
"label": "<string>",
"state": "active",
"issued_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"revoked_at": "2023-11-07T05:31:56Z",
"revocation_reason": "principal",
"connection_uri": "<string>",
"psql_command": "<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/resource-not-found",
"title": "Resource not found",
"status": 404,
"code": "resource_not_found",
"request_id": "req_01J00000000000000000000000",
"retryable": false,
"suggested_action": "Check the resource identifier and your access scope."
}{
"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
}Issue one time-bound PostgreSQL credential for Dev or Prod
Owner-authorized direct PostgreSQL login for the project’s own database, returned exactly once and never retrievable again. Mode read joins the read-only role, mode write joins the same restricted runtime role the application uses; neither can change schema, and application row-level security policies remain effective. The lifetime is 5 minutes to 24 hours (3600 seconds by default) and PostgreSQL refuses new logins after it; the platform ends remaining sessions within 15 minutes after expiry, at the latest. At most three active credentials exist per project environment. Database compute wakes and is metered normally, and existing credit grace and Stop budgets apply. Revoke the credential as soon as the work is finished and never store the connection URI in files, notes or source.
curl --request POST \
--url https://app.ohmyho.st/v1/projects/{project_id}/database/access \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"mode": "read",
"ttl_seconds": 3600,
"label": "<string>"
}
'import requests
url = "https://app.ohmyho.st/v1/projects/{project_id}/database/access"
payload = {
"mode": "read",
"ttl_seconds": 3600,
"label": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({mode: 'read', ttl_seconds: 3600, label: '<string>'})
};
fetch('https://app.ohmyho.st/v1/projects/{project_id}/database/access', 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/{project_id}/database/access",
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([
'mode' => 'read',
'ttl_seconds' => 3600,
'label' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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/{project_id}/database/access"
payload := strings.NewReader("{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
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/{project_id}/database/access")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.ohmyho.st/v1/projects/{project_id}/database/access")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"mode\": \"read\",\n \"ttl_seconds\": 3600,\n \"label\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"access_id": "<string>",
"environment": "dev",
"mode": "read",
"role_name": "<string>",
"host": "<string>",
"database": "neondb",
"label": "<string>",
"state": "active",
"issued_at": "2023-11-07T05:31:56Z",
"expires_at": "2023-11-07T05:31:56Z",
"revoked_at": "2023-11-07T05:31:56Z",
"revocation_reason": "principal",
"connection_uri": "<string>",
"psql_command": "<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/resource-not-found",
"title": "Resource not found",
"status": 404,
"code": "resource_not_found",
"request_id": "req_01J00000000000000000000000",
"retryable": false,
"suggested_action": "Check the resource identifier and your access scope."
}{
"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 - 128Path Parameters
Project identifier.
^[0-9A-HJKMNP-TV-Z]{26}$Body
dev, prod read joins the read-only role; write joins the restricted runtime role. Neither can change schema.
read, write Credential lifetime between 5 minutes and 24 hours.
300 <= x <= 86400Optional customer label without control characters or surrounding whitespace.
1 - 64Response
The connection URI is returned once and is never persisted in plaintext.
^[0-9A-HJKMNP-TV-Z]{26}$dev, prod read, write ^ohmyho_da_[0-7][0-9a-hjkmnp-tv-z]{25}_[0-9a-z]{8}$1 - 253"neondb"1 - 64active, expired, revoked principal, expired, budget, creation_failed, null Returned exactly once. Use it immediately and never store it in files, notes or source.
The same credential as a ready psql invocation.