Make your first API request
Get an access token, list your services and refresh the token when it expires, with curl commands you can copy.
This tutorial takes you from your email and password to a working API session in a terminal. You sign in, read your account, list your services and renew the access token when it runs out. Every request goes to https://api.coritan.com/api/v1.
Before you begin
Section titled Before you begin- A Coritan account with a password. Create an account if you have none.
curl, andjqto read values out of the JSON answers.- Your authenticator app, if you turned on two-factor authentication.
Important
The API accepts the access token that signing in returns. It does not accept the keys from Settings, API keys (they start with ct_): a request that sends one answers 401. Manage API keys explains what the keys are for today.
1. Check whether sign-in needs a challenge
Section titled 1. Check whether sign-in needs a challengeThe sign-in page can ask for a bot check. Ask the API whether it is on:
curl https://api.coritan.com/api/v1/auth/turnstile
{"enabled": false, "site_key": ""}
When enabled is false, an email and a password are enough to sign in, and you can go on to the next section. When it is true, POST /auth/login also needs a turnstile_token that only the check on the sign-in page produces. Without one it answers 403 with {"detail": {"error": "turnstile_failed", "message": "Verification required"}}, so a script cannot sign in on its own.
You now know whether your password is enough to sign in from a terminal.
2. Sign in and keep the tokens
Section titled 2. Sign in and keep the tokensRead your password into a variable, so it stays out of your shell history:
Shellread -rs -p "Password: " CORITAN_PASSWORD; echoSign in with
POST /auth/login.jqbuilds the JSON body, so a password with quotes or other special characters is sent intact:Shellcurl -s -X POST https://api.coritan.com/api/v1/auth/login \ -H "Content-Type: application/json" \ -d "$(jq -n --arg email alex@example.com --arg password "$CORITAN_PASSWORD" '{email: $email, password: $password}')" \ > login.jsonWithout two-factor authentication,
login.jsonholds your tokens:JSON{ "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "bearer", "expires_in": 1800 }expires_inis how many seconds the access token lasts.If you use two-factor authentication, the answer asks for your code instead:
JSON{"mfa_required": true, "mfa_setup_required": false, "mfa_token": "eyJhbGciOiJIUzI1NiIs...", "expires_in": 600, "token_type": "bearer"}Send the code from your app with
POST /auth/mfa/verifywithin ten minutes, withmfa_tokenas the bearer token. A recovery code works too, once. The answer holds the same tokens as a sign-in without a second factor:ShellMFA_TOKEN=$(jq -r .mfa_token login.json) curl -s -X POST https://api.coritan.com/api/v1/auth/mfa/verify \ -H "Authorization: Bearer $MFA_TOKEN" \ -H "Content-Type: application/json" \ -d '{"code": "123456"}' \ > login.jsonKeep both tokens in variables:
Shellexport CORITAN_TOKEN=$(jq -r .access_token login.json) CORITAN_REFRESH=$(jq -r .refresh_token login.json)
echo "$CORITAN_TOKEN" now prints a long string that starts with eyJ. Keep login.json private or delete it: anyone with these tokens can use your account.
3. Read your account
Section titled 3. Read your accountSend the access token in the Authorization header of every request. GET /auth/me returns the account the token belongs to:
curl -s https://api.coritan.com/api/v1/auth/me \
-H "Authorization: Bearer $CORITAN_TOKEN"
{
"id": 4821,
"email": "alex@example.com",
"first_name": "Alex",
"last_name": null,
"company": null,
"status": "active",
"billing_mode": "prepaid",
"credit_balance": 25.0,
"currency": "USD",
"country_code": "GB",
"currency_source": "default",
"created_at": "2026-09-01T10:15:00"
}
The email is yours, which shows the token works. Update your profile describes each field.
4. List your services
Section titled 4. List your servicesGET /services/ returns a JSON array of the services on your account, newest first. This prints one line for each of the first five:
curl -s "https://api.coritan.com/api/v1/services/?limit=5" \
-H "Authorization: Bearer $CORITAN_TOKEN" \
| jq -c '.[] | {id, hostname, status, product_name}'
{"id":1042,"hostname":"web-1.example.com","status":"active","product_name":"Cloud Compute 2 GB"}
An account with no services prints nothing. You see the same services as on the Services page. Manage your services lists the filters and fields.
5. Renew the access token
Section titled 5. Renew the access tokenWhen the access token runs out, every request answers 401 with Invalid or expired token. Exchange the refresh token for a new pair with POST /auth/refresh. It needs no password, no bot check and no second factor:
curl -s -X POST https://api.coritan.com/api/v1/auth/refresh \
-H "Content-Type: application/json" \
-d "$(jq -n --arg token "$CORITAN_REFRESH" '{refresh_token: $token}')" \
> login.json
export CORITAN_TOKEN=$(jq -r .access_token login.json)
CORITAN_REFRESH=$(jq -r .refresh_token login.json)
The answer has the same fields as a sign-in. Keep the new refresh_token each time: it starts a full lifetime of its own, while the one you sent keeps its old expiry. When a refresh token has expired too, sign in again as in section 2.
Run the GET /auth/me request from section 3 again. It answers with your account, using the new token.
Troubleshooting
Section titled Troubleshooting401Invalid email or password- The email or the password is wrong. The answer is the same for both.
403Account is suspended or closed- The account cannot sign in. Contact support.
401That code is not right- The code is wrong, or you used it already: each code from the app works once. Wait for the next one.
401Invalid or expired tokenfrom/auth/mfa/verify- The
mfa_tokenis more than ten minutes old. Sign in again. 401with"error": "mfa_required"- You sent the
mfa_tokento another endpoint. Finish section 2 first. 401Token invalidated by password change- Someone changed the account's password after the token was issued. Sign in again with the new password.
403Not authenticated- The request has no
Authorizationheader. Check that$CORITAN_TOKENis set in the shell you are using. 429Too many authentication attempts. Please try again later.- Too many sign-in or refresh attempts failed from your address. Wait a minute, as the
Retry-Afterheader says.
Related
Section titled Related- Authentication covers the token rules and the other kinds of credential.
- Errors and Rate limits describe what the API answers when a request fails.
- Sign out and end sessions explains how to stop a token working.
- The Client API reference lists every endpoint. api.coritan.com/docs lets you try them in the browser.
API operations on this page
| Method | Path | What it does |
|---|---|---|
GET | /api/v1/auth/turnstile | Turnstile config |
POST | /api/v1/auth/login | Login |
POST | /api/v1/auth/mfa/verify | Second step of signing in |
GET | /api/v1/auth/me | Get me |
GET | /api/v1/services/ | List services |
POST | /api/v1/auth/refresh | Refresh |