Skip to content

Overview

We'll walk through our organization endpoint /v2/organization which allows you to retrieve metadata about your organization including all portfolios managed by the organization.

Authentication

Before making a request, you need to generate an API key and secret. Refer to the api keys section of the overview for details on how to obtain your API credentials.

To authenticate your request for organization routes, you must generate a signature using your API key and secret, and include your organization ID. The request headers should include:

  • x-definitive-api-key: Your API key
  • x-definitive-signature: A signature generated using your API secret
  • x-definitive-timestamp: The current timestamp
  • x-definitive-organization-id: Your organization ID (sent as header but NOT included in signature)

:::warning Important For GET /v2/organization and most organization-level endpoints, do NOT include the x-definitive-organization-id header in your request. Instead, provide the organizationId as a query string parameter (e.g., ?organizationId=...). Only include x-definitive-api-key, x-definitive-timestamp, and x-definitive-signature headers. For portfolio-scoped routes, the portfolioId in the path is sufficient and the org header is not needed. :::

Making Your First Request

Here we'll dive into an example request, getting organization details from /v2/organization. Please note that we've included a helper class AuthHelpers in the request authorization section to make this easier but we will be walking through the process manually here to help you understand how this works.

Step 1: Define API Key, Secret, Organization ID, and Timestamp

You'll need to access these values in the next few steps.

const apiKey = process.env.API_KEY;
const apiSecret = process.env.API_SECRET;
const organizationId = "00000000-0000-0000-0000-000000000000"; // Your organization ID
const timestamp = Date.now().toString();

Step 2: Prepare the Prehash

For maximum security we require that you use your api secret to sign the request that you're sending and that this signed request is submitted within 2 minutes of creation. To achieve this you must first create a "prehash" of the request. It should look like this:

${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString};

type PrehashParams = {
  method: "GET" | "POST" | "DELETE";
  path: string; // eg. /v2/organization
  timestamp: string; // stringified timestamp in ms
  headers: Record<string, string | number>;
  queryParams?: Record<string, string>;
  body?: string;
};
 
// if you're using typescript we recommend copying this method directly
function preparePrehash({
  method,
  timestamp,
  path,
  queryParams,
  headers,
  body,
}: PrehashParams) {
  // IMPORTANT: Only include these specific headers in the prehash
  // Do NOT include x-definitive-organization-id here
  const headersForPrehash: Record<string, string> = {
    "x-definitive-api-key": headers["x-definitive-api-key"] as string,
    "x-definitive-timestamp": headers["x-definitive-timestamp"] as string,
  };
 
  // ensure that the headers are sorted for consistency
  const sortedHeaders = Object.entries(headersForPrehash)
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([key, value]) => `${key}:${JSON.stringify(value)}`)
    .join(",");
 
  // stringify the query params eg. 'key=value&key2=value2'
  const queryParamsString = new URLSearchParams(queryParams).toString();
 
  const bodyString = body ?? "";
 
  return `${method}:${path}?${queryParamsString}:${timestamp}:${sortedHeaders}${bodyString}`;
}
 
const timestamp = Date.now().toString();
 
// generate the message to be signed
const message = preparePrehash({
  method: "GET",
  path: "/v2/organization",
  timestamp,
  headers: {
    "x-definitive-api-key": apiKey,
    "x-definitive-timestamp": timestamp,
    // NOTE: Do not include organization ID here
  },
  queryParams: {},
});

Step 3: Sign the Request

Remove the dpks_ prefix from your api secret and use the resulting string to generate an HMAC of the secret and message.

const secret = apiSecret.replace("dpks_", "");
const signature = crypto
  .createHmac("sha256", secret)
  .update(message)
  .digest("hex");

Step 4: Make the request

This request will return details about your organization and all portfolios within it. Do not include the organization ID header in the request.

// Send request
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,
  },
});
 
// Parse response
const json = await result.json();
console.log(json);

Using AuthHelpers (Recommended)

For easier development, use the AuthHelpers class from the request authorization section. Important: Always include the organizationId parameter for organization routes:

import { AuthHelpers } from "./auth-helpers";
 
const json = await AuthHelpers.signAndSend({
  path: "/v2/organization",
  method: "GET",
  organizationId: "00000000-0000-0000-0000-000000000000",
});
console.log(json);

Response Format

The response will include organization details and all portfolios:

{
  "data": [
    {
      "portfolioId": "00000000-0000-0000-0000-000000000001",
      "portfolioName": "Trading Portfolio",
      "createdAt": "2024-08-05T20:48:11.584Z"
    }
    // ... additional portfolios
  ],
  "pagination": {
    "hasMore": false,
    "nextCursor": null,
    "limit": 10
  }
}

Common Authentication Errors

Invalid API Authentication

If you see this error, check:

  1. Are you including x-definitive-organization-id in the prehash? (You shouldn't!)
  2. Are your headers sorted alphabetically in the prehash?
  3. Are header values JSON.stringified with quotes?
  4. Is your timestamp within 2 minutes of the current time?

Example of CORRECT prehash headers:

// Only these two headers in prehash:
const headersForPrehash = {
  "x-definitive-api-key": apiKey,
  "x-definitive-timestamp": timestamp,
};

Example of INCORRECT prehash headers:

// DON'T DO THIS - organization ID should not be in prehash
const headersForPrehash = {
  "x-definitive-api-key": apiKey,
  "x-definitive-timestamp": timestamp,
  "x-definitive-organization-id": organizationId, // WRONG!
};

Error Handling

If the request fails, the API will return an error response with an appropriate status code and message. Common errors include:

  • 401 Unauthorized: Invalid or missing API key/signature
  • 403 Forbidden: Access denied or invalid organization ID
  • 408 Request Timeout: Timestamp is too old (>2 minutes)
  • 500 Internal Server Error: Unexpected server error

Next Steps

Now that you understand the basics, explore other organization endpoints:

Key Differences from Portfolio API

When using organization routes, remember:

  1. Always include organizationId in your AuthHelpers.signAndSend calls
  2. Never include x-definitive-organization-id in the signature calculation
  3. Organization routes manage multiple portfolios within an organization
  4. Portfolio routes work with a single portfolio scope

Summary

To access organization data:

  1. Generate a prehash message with ONLY x-definitive-api-key and x-definitive-timestamp
  2. Sign the prehash using your API secret
  3. Send a request with all required headers (do NOT include x-definitive-organization-id for GET /v2/organization or portfolio-scoped routes)
  4. Handle the response and possible errors appropriately

For further details, refer to the specific endpoint documentation in this section.