GET /user
GET /api/v1/user
Section titled “GET /api/v1/user”Get authenticated user information and accessible teams.
Overview
Section titled “Overview”This endpoint returns the email address of the authenticated user and a list of teams they have access to. Use this endpoint to:
- Verify authentication is working correctly
- Discover which teams are available for scenario operations
- Get team IDs to use in other API calls
Authentication
Section titled “Authentication”Required: RSA signature-based authentication
X-Auth-Client-ID: {clientId}X-Auth-Access-Token: {accessToken}X-Auth-Timestamp: {timestamp}X-Auth-Nonce: {nonce}X-Auth-Signature: {signature}Request
Section titled “Request”Method: GET
URL: https://api.quickli.com/api/v1/user
Headers:
X-Auth-Client-ID: {clientId}X-Auth-Access-Token: {accessToken}X-Auth-Timestamp: {timestamp}X-Auth-Nonce: {nonce}X-Auth-Signature: {signature}Content-Type: application/jsonBody: None
Response
Section titled “Response”Success Response (200 OK)
Section titled “Success Response (200 OK)”{ "data": { "email": "broker@example.com", "teams": [ { "id": "507f1f77bcf86cd799439011", "name": "Team Alpha" }, { "id": "507f191e810c19729de860ea", "name": "Team Beta" } ] }, "meta": { "timestamp": "2025-11-03T10:30:00.000Z", "version": "1.0.0" }}Response Fields
Section titled “Response Fields”| Field | Type | Description |
|---|---|---|
email | string | User’s email address |
teams | array | List of accessible teams |
teams[].id | string | Team ObjectId (use this in API calls requiring teamId) |
teams[].name | string | Team display name |
Error Responses
Section titled “Error Responses”401 Unauthorized
Section titled “401 Unauthorized”Authentication failed - invalid signature or credentials.
{ "error": { "code": "INVALID_SIGNATURE", "message": "Request signature verification failed", "timestamp": "2025-11-19T10:30:00.000Z" }}Causes:
- Invalid signature (signature verification failed)
- Invalid client identifier
- Invalid or expired access token
- Missing required authentication headers
- User not found
Solution: Verify your signature implementation and ensure all authentication headers are present and valid.
Code Examples
Section titled “Code Examples”# Note: You need to generate the signature for each request# See the Authentication Guide for signing implementationcurl -X GET https://api.quickli.com/api/v1/user \ -H "X-Auth-Client-ID: Loan Market Group" \ -H "X-Auth-Access-Token: abc123-uuid-token" \ -H "X-Auth-Timestamp: 2025-11-19T10:30:00.000Z" \ -H "X-Auth-Nonce: 550e8400-e29b-41d4-a716-446655440000" \ -H "X-Auth-Signature: {generated-signature}" \ -H "Content-Type: application/json"import crypto from "crypto";
const clientId = process.env.QUICKLI_CLIENT_ID!;const accessToken = process.env.QUICKLI_ACCESS_TOKEN!;const privateKey = process.env.QUICKLI_PRIVATE_KEY!;
function generateAuthHeaders(method: string, path: string, body: unknown) { const timestamp = new Date().toISOString(); const nonce = crypto.randomUUID();
// Handle empty body let bodyString = ""; if (body && typeof body === "object" && Object.keys(body).length > 0) { bodyString = JSON.stringify(body); }
const bodyHash = crypto.createHash("sha256").update(bodyString).digest("hex"); const canonicalRequest = `${method}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}`;
const sign = crypto.createSign("RSA-SHA256"); sign.update(canonicalRequest); const signature = sign.sign(privateKey, "base64");
return { "X-Auth-Client-ID": clientId, "X-Auth-Access-Token": accessToken, "X-Auth-Timestamp": timestamp, "X-Auth-Nonce": nonce, "X-Auth-Signature": signature, "Content-Type": "application/json", };}
async function getUser() { const headers = generateAuthHeaders("GET", "/api/v1/user", {});
const response = await fetch("https://api.quickli.com/api/v1/user", { method: "GET", headers, });
if (!response.ok) { const error = await response.json(); throw new Error(`API Error: ${error.error.message}`); }
const data = await response.json(); return data.data;}
// Usageconst user = await getUser();console.log("User email:", user.email);console.log("Available teams:", user.teams);
// Get first team ID for use in other callsconst firstTeamId = user.teams[0]?.id;import osimport hashlibimport base64import uuidfrom datetime import datetimeimport requestsfrom cryptography.hazmat.primitives import hashes, serializationfrom cryptography.hazmat.primitives.asymmetric import padding
def generate_auth_headers(method: str, path: str, body: dict | None): client_id = os.environ['QUICKLI_CLIENT_ID'] access_token = os.environ['QUICKLI_ACCESS_TOKEN'] private_key_pem = os.environ['QUICKLI_PRIVATE_KEY']
timestamp = datetime.utcnow().isoformat() + 'Z' nonce = str(uuid.uuid4())
# Handle empty body body_string = '' if body and len(body) > 0: import json body_string = json.dumps(body)
body_hash = hashlib.sha256(body_string.encode()).hexdigest() canonical_request = f"{method}\n{path}\n{timestamp}\n{nonce}\n{body_hash}"
private_key = serialization.load_pem_private_key( private_key_pem.encode(), password=None ) signature = private_key.sign( canonical_request.encode(), padding.PKCS1v15(), hashes.SHA256() ) signature_b64 = base64.b64encode(signature).decode()
return { 'X-Auth-Client-ID': client_id, 'X-Auth-Access-Token': access_token, 'X-Auth-Timestamp': timestamp, 'X-Auth-Nonce': nonce, 'X-Auth-Signature': signature_b64, 'Content-Type': 'application/json' }
def get_user(): headers = generate_auth_headers('GET', '/api/v1/user', None)
response = requests.get( 'https://api.quickli.com/api/v1/user', headers=headers )
response.raise_for_status() return response.json()['data']
# Usageuser = get_user()print(f"User email: {user['email']}")print(f"Available teams: {user['teams']}")
# Get first team ID for use in other callsfirst_team_id = user['teams'][0]['id'] if user['teams'] else NoneUse Cases
Section titled “Use Cases”1. Test Authentication
Section titled “1. Test Authentication”Use this endpoint to verify your credentials and signing implementation:
curl -X GET https://api.quickli.com/api/v1/user \ -H "X-Auth-Client-ID: {clientId}" \ -H "X-Auth-Access-Token: {accessToken}" \ -H "X-Auth-Timestamp: {timestamp}" \ -H "X-Auth-Nonce: {nonce}" \ -H "X-Auth-Signature: {signature}"If you get a 200 OK response, your authentication is configured correctly.
2. Get Available Teams
Section titled “2. Get Available Teams”Before creating scenarios, get the list of teams you can use:
const user = await getUser();
if (user.teams.length === 0) { console.error("No teams available. Contact your administrator.");} else { console.log("Available teams:"); user.teams.forEach((team) => { console.log(`- ${team.name} (ID: ${team.id})`); });}3. Select Team for Operations
Section titled “3. Select Team for Operations”Let users choose which team to work with:
const user = await getUser();
// In a UI, present team optionsconst selectedTeamId = await promptUserToSelectTeam(user.teams);
// Use selected team in scenario creationconst scenario = await createScenario({ teamId: selectedTeamId, scenario: { /* ... */ },});4. Cache Team Information
Section titled “4. Cache Team Information”Cache team data to avoid repeated calls:
class QuickliClient { private teams: Team[] | null = null;
async getTeams(): Promise<Team[]> { if (this.teams === null) { const user = await this.getUser(); this.teams = user.teams; } return this.teams; }
async getDefaultTeamId(): Promise<string> { const teams = await this.getTeams(); if (teams.length === 0) { throw new Error("No teams available"); } return teams[0].id; }}Team Access
Section titled “Team Access”Organization Scoping
Section titled “Organization Scoping”Your API access grant is scoped to one organization. All teams returned belong to that organization.
Team Permissions
Section titled “Team Permissions”The teams returned are those you have explicit permission to access via your ApiAccessGrant. You can:
- Create scenarios in any of these teams
- Read scenarios belonging to these teams
- Update scenarios in these teams
You cannot access:
- Teams from other organizations
- Teams not included in your access grant
Default Team Behavior
Section titled “Default Team Behavior”When creating scenarios, if you don’t specify a teamId, the API uses the first team in your list:
// These are equivalent:await createScenario({ scenario: { /* ... */ },});
await createScenario({ teamId: user.teams[0].id, scenario: { /* ... */ },});Integration Patterns
Section titled “Integration Patterns”SDK/Client Library
Section titled “SDK/Client Library”Wrap this endpoint in a client class:
class QuickliClient { constructor( private clientId: string, private accessToken: string, private privateKey: string, ) {}
private generateHeaders(method: string, path: string, body: unknown) { const timestamp = new Date().toISOString(); const nonce = crypto.randomUUID();
let bodyString = ""; if (body && typeof body === "object" && Object.keys(body).length > 0) { bodyString = JSON.stringify(body); }
const bodyHash = crypto .createHash("sha256") .update(bodyString) .digest("hex"); const canonicalRequest = `${method}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}`;
const sign = crypto.createSign("RSA-SHA256"); sign.update(canonicalRequest); const signature = sign.sign(this.privateKey, "base64");
return { "X-Auth-Client-ID": this.clientId, "X-Auth-Access-Token": this.accessToken, "X-Auth-Timestamp": timestamp, "X-Auth-Nonce": nonce, "X-Auth-Signature": signature, "Content-Type": "application/json", }; }
private async request(path: string, method: string = "GET", body?: unknown) { const headers = this.generateHeaders(method, path, body);
const response = await fetch(`https://api.quickli.com${path}`, { method, headers, body: body ? JSON.stringify(body) : undefined, });
if (!response.ok) { const error = await response.json(); throw new Error(error.error.message); }
return response.json(); }
async getUser() { const result = await this.request("/api/v1/user"); return result.data; }}
// Usageconst client = new QuickliClient( process.env.QUICKLI_CLIENT_ID!, process.env.QUICKLI_ACCESS_TOKEN!, process.env.QUICKLI_PRIVATE_KEY!,);
const user = await client.getUser();Initialization Check
Section titled “Initialization Check”Verify credentials during application startup:
async function initializeApp() { try { const user = await getUser(); console.log(`✓ Authenticated as ${user.email}`); console.log(`✓ ${user.teams.length} team(s) available`); return true; } catch (error) { console.error("✗ Authentication failed:", error.message); return false; }}
// Only proceed if authentication worksif (!(await initializeApp())) { process.exit(1);}Response Validation
Section titled “Response Validation”TypeScript Types
Section titled “TypeScript Types”interface User { email: string; teams: Team[];}
interface Team { id: string; // MongoDB ObjectId as string name: string;}
interface UserResponse { data: User; meta: { timestamp: string; version: string; };}Runtime Validation
Section titled “Runtime Validation”import { z } from "zod/v3";
const TeamSchema = z.object({ id: z.string().length(24), // MongoDB ObjectId name: z.string(),});
const UserSchema = z.object({ email: z.string().email(), teams: z.array(TeamSchema),});
const UserResponseSchema = z.object({ data: UserSchema, meta: z.object({ timestamp: z.string(), version: z.string(), }),});
// Validate responseconst response = await fetch("...");const json = await response.json();const validated = UserResponseSchema.parse(json);See Also
Section titled “See Also”- Authentication Guide - Details on RSA signature authentication
- Create Scenario - Use team IDs to create scenarios
- Error Handling - Handle authentication errors
Last updated: 2025-11-19