Skip to main content

Authenticate with AI Smart Redact

The Orchestrator API uses JWT bearer tokens for authentication. This guide covers the authentication flow, first log-in setup, API key authentication for automated workflows, and command-line examples.

Overview

Two tokens are involved in the authentication flow:

TokenLifetimePurpose
Access token15 minutesShort-lived JWT sent as Authorization: Bearer <TOKEN> on every request.
Refresh token30 daysLong-lived opaque token stored as an HttpOnly cookie scoped to /v1/auth. Used to obtain new access tokens without re-entering credentials.

All endpoints require an access token except POST /v1/auth/login and POST /v1/auth/refresh.

info

The refresh token cookie is scoped to /v1/auth. The browser only sends this cookie on requests to /v1/auth/* paths (such as /v1/auth/refresh). It isn’t sent on other API paths like /v1/users. If your refresh request isn’t including the cookie, verify the request URL starts with /v1/auth.

Default credentials

A seeded admin account is created automatically on first startup:

FieldValue
Emailadmin@example.com
PasswordAdmin@1234!Tmp

The account has the PasswordResetRequired flag set. Change this password immediately after the first log in.

First log-in flow

  1. Call POST /v1/auth/login with the default credentials.
  2. The response contains an access token with a password_reset_required claim.
  3. Call POST /v1/auth/reset-password with the token from step 2 to set a new password.
  4. Use the new access token returned by step 3 for all subsequent requests.
info

The password reset isn’t enforced. You can use other endpoints without resetting first. However, changing the default password immediately is strongly recommended.

JWT configuration

Setting used (Orchestrator): Jwt.SecretKey. Generate the value with the command below.

The Orchestrator signs JWT tokens with an HMAC-SHA256 secret key. Generate one and set it before starting the Orchestrator:

openssl rand -base64 64 | tr -d '\n'
environment:
Jwt__SecretKey: "<JWT_SECRET_KEY>"

For the full settings catalog (SecretKey, ExpirationMinutes, RefreshTokenExpirationDays), refer to Orchestrator > JWT.

Command-line usage

The following examples use curl. Save the Orchestrator base URL to a variable:

BASE_URL=http://localhost:9983

Log in

curl -s -c cookies.txt -X POST "$BASE_URL/v1/auth/login" \
-H "Content-Type: application/json" \
-d '{"login": "admin@example.com", "password": "Admin@1234!Tmp"}' | tee login_response.json

Extract the token:

TOKEN=$(grep -o '"token":"[^"]*"' login_response.json | cut -d'"' -f4)

Reset password (first log in)

curl -s -c cookies.txt -b cookies.txt -X POST "$BASE_URL/v1/auth/reset-password" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"newPassword": "MySecurePassword1!"}' | tee reset_response.json

TOKEN=$(grep -o '"token":"[^"]*"' reset_response.json | cut -d'"' -f4)

Call a protected endpoint

curl -s -X GET "$BASE_URL/v1/users" \
-H "Authorization: Bearer $TOKEN"

Refresh the access token

When the access token expires, use the saved cookie to refresh it:

curl -s -c cookies.txt -b cookies.txt -X POST "$BASE_URL/v1/auth/refresh" | tee refresh_response.json

TOKEN=$(grep -o '"token":"[^"]*"' refresh_response.json | cut -d'"' -f4)

The refresh token is automatically rotated. The cookie file is updated with the new value.

Change password

curl -s -X POST "$BASE_URL/v1/auth/change-password" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{"currentPassword": "OldPassword1!", "newPassword": "NewPassword1!"}'

All existing refresh tokens are revoked and a new access token is returned.

Log out

curl -s -b cookies.txt -X POST "$BASE_URL/v1/auth/logout" \
-H "Authorization: Bearer $TOKEN"

API key authentication

API keys provide non-interactive authentication for automated scripts and integrations. Unlike JWT, API keys don’t require a log-in flow. Send the key directly in a request header.

How API keys work

  1. An admin creates an API key for a specific user through POST /v1/api-keys.
  2. The raw key (for example, pdft_AbCdEf...) is returned once in the response. It can’t be retrieved later.
  3. Include the key in every request using the X-Api-Key header.
  4. The server hashes the key, looks it up in the database, and authenticates the request as the linked user.

Key details

PropertyValue
Formatpdft_ prefix + 32 cryptographically random bytes (base64url, ~48 characters total)
StorageOnly the SHA-256 hash is stored in the database
ExpirationRequired when creating, maximum 12 months
ScopeJobs endpoints only (POST /v1/jobs, GET /v1/jobs, GET /v1/jobs/{id}, POST /v1/jobs/{id}/redaction, GET /v1/jobs/{id}/files/{fileType})

Create an API key (admin)

curl -s -X POST "$BASE_URL/v1/api-keys" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $TOKEN" \
-d '{
"name": "CI Pipeline Key",
"userId": "<USER_ID>",
"expiresAt": "2027-01-01T00:00:00Z"
}'

Replace <USER_ID> with the ID of the user the key authenticates as. Save the raw key field from the response immediately. It won’t be shown again.

Use an API key

# Upload a file
curl -s -X POST "$BASE_URL/v1/jobs" \
-H "X-Api-Key: pdft_your_key_here" \
-F "file=@document.pdf"

# List jobs
curl -s -X GET "$BASE_URL/v1/jobs" \
-H "X-Api-Key: pdft_your_key_here"

# Download redacted file
curl -s -X GET "$BASE_URL/v1/jobs/<JOB_ID>/files/redactedPdf" \
-H "X-Api-Key: pdft_your_key_here" \
--output redacted.pdf

Replace <JOB_ID> with the job identifier returned when the redaction job was created.

Revoke an API key (admin)

curl -s -X POST "$BASE_URL/v1/api-keys/<API_KEY_ID>/revoke" \
-H "Authorization: Bearer $TOKEN"

Replace <API_KEY_ID> with the API key’s ID (returned by GET /v1/api-keys). Revocation is immediate. The key is rejected on the next request.

Swagger UI

The Orchestrator Swagger UI is available at http://localhost:9983/swagger.

To authenticate in Swagger:

  1. Call POST /v1/auth/login to get an access token.
  2. Click the Authorize button (top right).
  3. In the Bearer (ApiKey) field, enter: Bearer <TOKEN> (include the Bearer prefix).
  4. Click Authorize, then Close.
info

After resetting or changing your password, re-authorize with the new token returned by the response.

Reset the admin user

If you’re locked out, delete the admin account from the database. It’s re-seeded with the default credentials on the next startup. The seeded admin’s username is admin (separate from the email address).

PostgreSQL (Docker)

docker exec -it smart-redact-orchestrator-db \
psql -U smartredact -d smartredact \
-c "DELETE FROM \"AspNetUsers\" WHERE \"UserName\" = 'admin';"

docker compose restart smart-redact-orchestrator