API reference
Console session endpoints
The Developer workspace in the portal uses these. Script them only if you manage apps or webhooks from code; your app's users never call them.
Create an account
POST/v1/
Creates a CorrConnect account and, where email verification is off, signs it in. Where verification is on (production), the response is {"verification_required": true, "message": ...} and the account signs in after the emailed link is opened.
- Auth
- None; send
Origin - Host
- Portal origin only
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
Origin required | header | string | Exactly the CorrConnect portal origin. |
Request body application/json
| Field | Type | Notes |
|---|---|---|
email required | string | Your email address; it is stored in lower case. 3 to 254 characters |
password required | string | 12 to 128 characters using at least three of: uppercase, lowercase, number, symbol. 12 to 128 characters |
Response 201
Successful Response
Errors
| Status | Code | When |
|---|---|---|
| 403 | origin_rejected | The Origin header is not the exact CorrConnect portal origin. |
| 409 | account_exists | An account already uses this email address. |
| 422 | validation_ | A field is missing, has the wrong type or is out of range; details.fields says which. |
| 429 | rate_ | More than 5 sign-ups from one network address in an hour. |
curl "$CORRCONNECT_BASE/v1/account/register" \
-H "Origin: $CORRCONNECT_BASE" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "<at-least-12-characters>"}'const response = await fetch(`${process.env.CORRCONNECT_BASE}/v1/account/register`, {
method: "POST",
headers: {
"Origin": `${process.env.CORRCONNECT_BASE}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"email": "[email protected]", "password": "<at-least-12-characters>"}),
});
console.log(response.status, await response.json());import os
import requests
response = requests.post(
f"{os.environ['CORRCONNECT_BASE']}/v1/account/register",
headers={"Origin": f"{os.environ['CORRCONNECT_BASE']}"},
json={"email": "[email protected]", "password": "<at-least-12-characters>"},
timeout=10,
)
print(response.status_code, response.json())import Foundation
let env = ProcessInfo.processInfo.environment
var request = URLRequest(url: URL(string: "\(env["CORRCONNECT_BASE"]!)/v1/account/register")!)
request.httpMethod = "POST"
request.setValue("\(env["CORRCONNECT_BASE"]!)", forHTTPHeaderField: "Origin")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(#"{"email": "[email protected]", "password": "<at-least-12-characters>"}"#.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self)){
"verification_required": true,
"message": "Check your email for a verification link."
}Sign in
POST/v1/
Sets the session cookie and returns a CSRF token for changes.
- Auth
- None; send
Origin - Host
- Portal origin only
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
Origin required | header | string | Exactly the CorrConnect portal origin. |
Request body application/json
| Field | Type | Notes |
|---|---|---|
email required | string | The account's email address. 3 to 254 characters |
password required | string | The account's password. 1 to 128 characters |
Response 200
Successful Response
| Field | Type | Notes |
|---|---|---|
user required | object | |
user.id required | string | |
user.email required | string | |
csrf_token required | string | |
expires_at required | string (date-time) |
Errors
| Status | Code | When |
|---|---|---|
| 401 | invalid_ | The email or password is wrong. |
| 403 | origin_rejected | The Origin header is not the exact CorrConnect portal origin. |
| 403 | email_ | The account has not verified its email address yet. |
| 422 | validation_ | A field is missing, has the wrong type or is out of range; details.fields says which. |
| 429 | rate_ | More than 10 sign-in attempts from one network address in 15 minutes. |
curl "$CORRCONNECT_BASE/v1/account/login" \
-H "Origin: $CORRCONNECT_BASE" \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "password": "<your-password>"}'const response = await fetch(`${process.env.CORRCONNECT_BASE}/v1/account/login`, {
method: "POST",
headers: {
"Origin": `${process.env.CORRCONNECT_BASE}`,
"Content-Type": "application/json",
},
body: JSON.stringify({"email": "[email protected]", "password": "<your-password>"}),
});
console.log(response.status, await response.json());import os
import requests
response = requests.post(
f"{os.environ['CORRCONNECT_BASE']}/v1/account/login",
headers={"Origin": f"{os.environ['CORRCONNECT_BASE']}"},
json={"email": "[email protected]", "password": "<your-password>"},
timeout=10,
)
print(response.status_code, response.json())import Foundation
let env = ProcessInfo.processInfo.environment
var request = URLRequest(url: URL(string: "\(env["CORRCONNECT_BASE"]!)/v1/account/login")!)
request.httpMethod = "POST"
request.setValue("\(env["CORRCONNECT_BASE"]!)", forHTTPHeaderField: "Origin")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpBody = Data(#"{"email": "[email protected]", "password": "<your-password>"}"#.utf8)
let (data, response) = try await URLSession.shared.data(for: request)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self)){
"user": {
"id": "usr_0123456789abcdef0123456789abcdef",
"email": "[email protected]"
},
"csrf_token": "<csrf-token>",
"expires_at": "2026-10-10T00:00:00+00:00"
}Get the session and a fresh CSRF token
GET/v1/account/me
Each call issues a new CSRF token and retires the previous one. Call it before a change.
- Auth
- Console session cookie
- Host
- Portal origin only
Response 200
Successful Response
| Field | Type | Notes |
|---|---|---|
user required | object | |
user.id required | string | |
user.email required | string | |
csrf_token required | string |
Errors
| Status | Code | When |
|---|---|---|
| 401 | authentication_ | No console session cookie was sent. |
| 401 | invalid_session | The session was signed out, replaced or never existed. |
| 401 | session_expired | The session is older than its lifetime (12 hours by default). |
| 403 | email_ | The account has not verified its email address yet. |
curl "$CORRCONNECT_BASE/v1/account/me" \
-H "Cookie: $CORRCONNECT_COOKIE"const response = await fetch(`${process.env.CORRCONNECT_BASE}/v1/account/me`, {
headers: {
"Cookie": `${process.env.CORRCONNECT_COOKIE}`,
},
});
console.log(response.status, await response.json());import os
import requests
response = requests.get(
f"{os.environ['CORRCONNECT_BASE']}/v1/account/me",
headers={"Cookie": f"{os.environ['CORRCONNECT_COOKIE']}"},
timeout=10,
)
print(response.status_code, response.json())import Foundation
let env = ProcessInfo.processInfo.environment
var request = URLRequest(url: URL(string: "\(env["CORRCONNECT_BASE"]!)/v1/account/me")!)
request.setValue("\(env["CORRCONNECT_COOKIE"]!)", forHTTPHeaderField: "Cookie")
let (data, response) = try await URLSession.shared.data(for: request)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self)){
"user": {
"id": "usr_0123456789abcdef0123456789abcdef",
"email": "[email protected]"
},
"csrf_token": "<csrf-token>"
}Sign out
POST/v1/
Ends this session and clears the cookie.
- Auth
- Console session cookie,
OriginandX-CSRF-Token - Host
- Portal origin only
Parameters
| Name | In | Type | Notes |
|---|---|---|---|
Origin required | header | string | Exactly the CorrConnect portal origin. |
X-CSRF-Token required | header | string | The latest csrf_token from sign-in or GET /v1/account/me. |
Response 200
Successful Response
| Field | Type | Notes |
|---|---|---|
status required | string | One of signed_out |
Errors
| Status | Code | When |
|---|---|---|
| 401 | authentication_ | No console session cookie was sent. |
| 401 | invalid_session | The session was signed out, replaced or never existed. |
| 401 | session_expired | The session is older than its lifetime (12 hours by default). |
| 403 | email_ | The account has not verified its email address yet. |
| 403 | origin_rejected | The Origin header is not the exact CorrConnect portal origin. |
| 403 | csrf_rejected | X-CSRF-Token is missing or is not the latest token from GET /v1/account/me. |
curl -X POST "$CORRCONNECT_BASE/v1/account/logout" \
-H "Cookie: $CORRCONNECT_COOKIE" \
-H "Origin: $CORRCONNECT_BASE" \
-H "X-CSRF-Token: $CSRF_TOKEN"const response = await fetch(`${process.env.CORRCONNECT_BASE}/v1/account/logout`, {
method: "POST",
headers: {
"Cookie": `${process.env.CORRCONNECT_COOKIE}`,
"Origin": `${process.env.CORRCONNECT_BASE}`,
"X-CSRF-Token": `${process.env.CSRF_TOKEN}`,
},
});
console.log(response.status, await response.json());import os
import requests
response = requests.post(
f"{os.environ['CORRCONNECT_BASE']}/v1/account/logout",
headers={"Cookie": f"{os.environ['CORRCONNECT_COOKIE']}", "Origin": f"{os.environ['CORRCONNECT_BASE']}", "X-CSRF-Token": f"{os.environ['CSRF_TOKEN']}"},
timeout=10,
)
print(response.status_code, response.json())import Foundation
let env = ProcessInfo.processInfo.environment
var request = URLRequest(url: URL(string: "\(env["CORRCONNECT_BASE"]!)/v1/account/logout")!)
request.httpMethod = "POST"
request.setValue("\(env["CORRCONNECT_COOKIE"]!)", forHTTPHeaderField: "Cookie")
request.setValue("\(env["CORRCONNECT_BASE"]!)", forHTTPHeaderField: "Origin")
request.setValue("\(env["CSRF_TOKEN"]!)", forHTTPHeaderField: "X-CSRF-Token")
let (data, response) = try await URLSession.shared.data(for: request)
print((response as! HTTPURLResponse).statusCode, String(decoding: data, as: UTF8.self)){
"status": "signed_out"
}