Skip to main content

Getting started with the API

Almost every Platform API endpoint is SigV4-signed, not Bearer-token-authenticated. So a simple "log in and use the JWT" mental model is wrong here. Plan on two steps after login for REST, plus one more if you also want MQTT.

The auth chain

StepEndpointAuth inAuth outWhen you need it
1. LoginPOST /v1/user/auth/token (Auth & Accounts)username + passwordaccesstoken (JWT)First time, and again every time the JWT expires (~1 hour). Refresh with /v1/user/auth/token/refresh.
2. Get AWS credentialsPOST /v1/user/credentials (User Credentials)JWT (CognitoAuthorizer)AccessKeyId + SecretAccessKey + SessionTokenMandatory for every REST call. The JWT itself only authorises this endpoint and a couple of account-level ones - everything else expects a SigV4-signed request (see below).
3. Assume IoT user rolePOST /v1/assumed-roles (Role Assumption)SigV4 with step-2 credsNew AccessKeyId + SecretAccessKey + SessionToken, IoT-scoped or group-scopedMQTT-only. Required for opening MQTT WebSocket connections (User MQTT API). Also how an admin narrows credentials to a specific group/subgroup. Not needed for any REST endpoint.

Rule of thumb:

  • Calling REST endpoints? Login → /v1/user/credentials → done. The step-2 creds work everywhere.
  • Connecting MQTT? Add step 3 to get IoT-role-scoped creds and use those for the WebSocket handshake.
  • Admin scoping to a single group/subgroup? Step 3 with group/subgroup in the body, then sign your REST calls with the returned creds instead of the step-2 ones.

What "SigV4-signed" means

SigV4 is AWS's standard request-signing scheme. You don't put any one of AccessKeyId, SecretAccessKey, or SessionToken directly into a header. Instead, all three are used together to compute an HMAC signature over the request, and the signature plus the AccessKeyId travel in the Authorization header:

Authorization: AWS4-HMAC-SHA256
Credential=AKIA.../20260501/<region>/execute-api/aws4_request,
SignedHeaders=content-type;host;x-amz-date;x-amz-security-token,
Signature=<hex>
X-Amz-Date: 20260501T120000Z
X-Amz-Security-Token: <SessionToken>

The SecretAccessKey is never sent over the wire — it's only used locally to derive the signature. The SessionToken rides along in X-Amz-Security-Token. If any of the three is missing or wrong, API Gateway rejects the request with a 403.

You almost never hand-roll this. Use:

  • AWS SDK (Go, JS, Python, Java, …) — pass the three credentials to a client, the SDK signs every request.
  • awscurl (github.com/okigan/awscurl) — drop-in curl replacement that reads AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN from the environment.
  • AWS CLI v2 with --sigv4 flag.

tl;dr in curl

BASE_URL=https://your-deployment.example.com
USER=you@example.com
PASS=Strongpass123!

# 1. Login -> JWT
JWT=$(curl -s -X POST "$BASE_URL/v1/user/auth/token" \
-H "Content-Type: application/json" \
-d "{\"user_name\":\"$USER\",\"password\":\"$PASS\"}" \
| jq -r .accesstoken)

# 2. JWT -> AWS credentials
CREDS=$(curl -s -X POST "$BASE_URL/v1/user/credentials" \
-H "Authorization: $JWT")
export AWS_ACCESS_KEY_ID=$(echo $CREDS | jq -r .access_key_id)
export AWS_SECRET_ACCESS_KEY=$(echo $CREDS | jq -r .secret_access_key)
export AWS_SESSION_TOKEN=$(echo $CREDS | jq -r .session_token)

# 3. (Optional) Step up to an IoT-scoped role - needed for MQTT etc.
# awscurl POST "$BASE_URL/v1/assumed-roles" --service execute-api ...

# 4. Call any platform endpoint (SigV4-signed)
awscurl --service execute-api "$BASE_URL/v1/user/groups"

awscurl (github.com/okigan/awscurl) handles SigV4 signing for you. The AWS CLI v2 --sigv4 flag works too.

Authentication models in the spec

The Platform API exposes two security schemes; each endpoint page tells you which one applies via the Authorization badge in the right-hand panel.

CognitoAuthorizer — only for two endpoints

A Cognito User Pool JWT in the Authorization header. No Bearer prefix — the raw token:

Authorization: eyJraWQiOiJ...

Used only by /v1/user/credentials and a single admin endpoint. Everything else uses SigV4.

sigv4 — the rest

AWS SigV4 signing with the AccessKeyId / SecretAccessKey / SessionToken triplet from step 2 (or step 3 for IoT operations).

If you're hand-rolling: Authorization header looks like

Authorization: AWS4-HMAC-SHA256 Credential=AKIA.../20260501/<region>/execute-api/aws4_request, SignedHeaders=..., Signature=...

…and the request also needs X-Amz-Date and X-Amz-Security-Token. Easier path: use the AWS SDK or awscurl.

Login flow (Auth & Accounts API)

The full lifecycle for end users lives under /v1/user/auth/*:

StepEndpointPurpose
Register a new userPOST /v1/user/auth/signupCreates the account, mails a verification code.
Confirm registrationPOST /v1/user/auth/signup/verifySubmits the code from the email.
Login (Create Token)POST /v1/user/auth/tokenExchanges username/password for tokens. Start here.
Refresh access tokenPOST /v1/user/auth/token/refreshTrade refreshtoken for a new accesstoken.
Request password resetPOST /v1/user/auth/password-recoveryMails a reset code.
Complete password resetPOST /v1/user/auth/password-recovery/confirmationSubmits the new password.
Change password (logged in)POST /v1/user/auth/passwordRequires a valid access token.

Admin equivalents live under /v1/admin/auth/* — same shape, different user pool.

The login response shape:

{
"status": "success",
"accesstoken": "eyJraWQ...",
"refreshtoken": "eyJjdHk...",
"idtoken": "eyJraWQ..."
}

Using "Try it out" in this site

Each endpoint page has a right-hand panel. From top to bottom:

  1. Base URL. Defaults to https://api.example.com/dev. Click the Edit button on the right edge of that box - a text input appears with the placeholder api.example.com. Replace it with your deployment's API Gateway hostname (e.g. api.dev.rmng.example.com). The change persists across endpoint pages within the session.
  2. Auth. Pick the security scheme. CognitoAuthorizer takes the raw JWT in a single field; sigv4 takes AccessKeyId, SecretAccessKey, and SessionToken in three fields.
  3. Parameters / Body. Pre-populated from the spec, edit as needed.
  4. Send API Request. Fires a real request from your browser. Sits at the very bottom of the panel - scroll down past the parameters if you don't see it.

CORS heads-up

API Gateway ships with strict CORS by default, so a browser-side Try-it-out from localhost:3000 (or the docs site itself) will fail preflight unless your stack permits the origin. Either:

  • Add localhost:3000 to the corsAllowedOrigins setting in your CDK config and redeploy, or
  • Use the equivalent curl/awscurl snippet from the page's Code Samples panel.

What about the MQTT APIs?

Devices use X.509 client certs (provisioned during factory NVS generation — see Factory provisioning). User clients use SigV4 over WebSockets — those are the credentials from step 3 (/v1/assumed-roles "Assume IoT user role"), not step 2.

The Node MQTT and User MQTT pages render the AsyncAPI specs inline.