Making Your First Request
This guide walks through making your first authenticated request to the Definitive API. The same authentication mechanism applies to both the Portfolio API and the Organization API — the only difference is the URL paths.
Authentication
Before making a request, generate an API key and secret. See Generate an API Key in the Overview guide for details.
All authenticated requests require these headers:
x-definitive-api-key: Your API keyx-definitive-signature: A signature generated using your API secretx-definitive-timestamp: The current timestamp
Making Your First Request
We'll walk through a request step by step. A helper class AuthHelpers is available in the Request Authorization section to simplify this, but we'll go through the manual process first.
Step 1: Define API Key, Secret, and Timestamp
const apiKey = process.env.API_KEY;
const apiSecret = process.env.API_SECRET;
const timestamp = Date.now().toString();Step 2: Prepare the Prehash
For security, all requests must be signed and submitted within 2 minutes. The prehash format is:
${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString};
type PrehashParams = {
method: "GET" | "POST" | "DELETE";
path: string;
timestamp: string;
headers: Record<string, string | number | object>;
queryParams?: Record<string, string>;
body?: string;
};
function preparePrehash({
method,
timestamp,
path,
queryParams,
headers,
body,
}: PrehashParams) {
const filtered = Object.entries(headers).filter(([key]) =>
key.toLowerCase().startsWith("x-definitive-"),
);
const sortedHeaders = filtered
.sort(([a], [b]) => a.localeCompare(b))
.map(([key, value]) => `${key}:${JSON.stringify(value)}`)
.join(",");
// only pass x-definitive-api-key and x-definitive-timestamp
if (filtered.length > 2) {
throw new Error("Headers are too long - are you adding a new header?");
}
const queryParamsString = new URLSearchParams(queryParams).toString();
const bodyString = body ?? "";
return `${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString}`;
}Step 3: Sign the Request
Remove the dpks_ prefix from your API secret and generate an HMAC SHA-256 signature:
const secret = apiSecret.replace("dpks_", "");
const signature = crypto
.createHmac("sha256", secret)
.update(message)
.digest("hex");Step 4: Make the Request
Portfolio API
const result = await fetch("https://ddp.definitive.fi/v2/portfolio/orders", {
method: "GET",
headers: {
"x-definitive-api-key": apiKey,
"x-definitive-signature": signature,
"x-definitive-timestamp": timestamp,
},
});
const json = await result.json();Organization API
const result = await fetch("https://ddp.definitive.fi/v2/organization", {
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
"x-definitive-api-key": apiKey,
"x-definitive-signature": signature,
"x-definitive-timestamp": timestamp,
},
});
const json = await result.json();Using AuthHelpers (Recommended)
The AuthHelpers class from the Request Authorization section handles prehashing and signing automatically:
import { AuthHelpers } from "./auth-helpers";
// Portfolio API
const portfolioOrders = await AuthHelpers.signAndSend({
path: "/v2/portfolio/orders",
method: "GET",
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});
// Organization API
const orgData = await AuthHelpers.signAndSend({
path: "/v2/organization",
method: "GET",
apiKey: process.env.API_KEY,
apiSecret: process.env.API_SECRET,
});Common Authentication Errors
If you see 401 Unauthorized or Invalid API Authentication, check:
- Are your headers sorted alphabetically in the prehash?
- Are header values
JSON.stringify'd with quotes? - Is your timestamp within 2 minutes of the current time?
Correct prehash headers
const headersForPrehash = {
"x-definitive-api-key": apiKey,
"x-definitive-timestamp": timestamp,
};Error Handling
Common error responses:
400 Bad Request: Invalid request body, or a rejected order (e.g. cross-chain slippage mismatch)401 Unauthorized: Invalid or missing API key/signature403 Forbidden: Access denied or invalid organization ID408 Request Timeout: Timestamp is too old (>2 minutes)422 Unprocessable Entity: Not currently executable (e.g. cross-chain trading vault still initializing)500 Internal Server Error: Unexpected server error
See Error Codes for the full list.
Next Steps
- Portfolio API users: Explore Portfolio Details, Positions, and Trading
- Organization API users: Start with List Portfolios, then Create Portfolio and Trading