> ## Documentation Index
> Fetch the complete documentation index at: https://docs.useparagon.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Tools API

> Give your AI agent or app access to thousands of tools from your users' integrations, from our catalog of pre-built Tools.

ActionKit **Tools API** provides our complete library of pre-built tools (actions in third-party systems) to expose as capabilities for AI agents, workflow builders, or other front-end functions that require integration data.

## API Usage

**Base URL**

```js theme={null}
https://actionkit.useparagon.com/projects/[Project ID]
```

<Accordion title="For on-premise instances">
  ```js theme={null}
  https://worker-actionkit.[On-Prem Base URL]/projects/[Project ID]
  ```
</Accordion>

**Authentication**

To authenticate to ActionKit API, present a Bearer token with the Paragon User Token (a JWT):

```js theme={null}
Authorization: Bearer [Paragon User Token]
```

This is the same token that you used to call `.authenticate` with the Paragon SDK. See examples in [Installing the SDK](/getting-started/installing-the-connect-sdk).

<Info>
  If you are using [JWT Permissions](/apis/api-reference/jwt-permissions) to control access, your Paragon User Token must include the `actionkit` permission to make ActionKit API requests.
</Info>

## Pagination

Many list and search actions in ActionKit accept a `paginationParameters` object as part of the request `parameters`. When the result set exceeds a single page, the response includes a `pageCursor` (or equivalent token) that you pass in the next request to retrieve the following page.

A typical pagination flow looks like this:

1. Call an action without any pagination parameters to get the first page.
2. Check the response for a pagination cursor or token (e.g. `nextPageCursor`).
3. If a cursor is present, call the action again with the cursor in `paginationParameters`.
4. Repeat until no cursor is returned.

```js Example: Paginating Asana projects expandable theme={null}
// First request: no pagination parameters
const firstPage = await fetch(
  `https://actionkit.useparagon.com/projects/${projectId}/actions`,
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${userToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      action: "ASANA_GET_PROJECTS",
      parameters: {},
    }),
  }
);

const firstResult = await firstPage.json();
// Use firstResult.pageCursor for the next request

// Subsequent request: pass the page cursor
const nextPage = await fetch(
  `https://actionkit.useparagon.com/projects/${projectId}/actions`,
  {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${userToken}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      action: "ASANA_GET_PROJECTS",
      parameters: {
        paginationParameters: {
          pageCursor: firstResult.pageCursor,
        },
      },
    }),
  }
);
```

Paragon standardizes vendor-specific pagination mechanics into a few patterns:

| Parameter type | Description                                                                                                                                  | Fields                                          | Example integrations                                                                                                                                                                                                                       |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Cursor-based   | Receive `nextPageCursor` or `nextPageToken` and pass that field to `paginationParameters` in the next call.                                  | `pageCursor` or `pageToken`                     | [Asana](/actionkit/integrations/asana/ASANA_GET_PROJECTS), [Confluence](/actionkit/integrations/confluence/CONFLUENCE_SEARCH_PAGES), [Slack](/actionkit/integrations/slack/SLACK_LIST_CHANNELS)                                            |
| Offset-based   | Count the number of records received in a page and add it to a running `offset` parameter passed to `paginationParameters` in the next call. | `offset` or `skip`                              | [Mailchimp](/actionkit/integrations/mailchimp/MAILCHIMP_GET_CONTACTS_FROM_LIST), [Sage Intacct](/actionkit/integrations/sageintacct/SAGE_INTACCT_SEARCH_ACCOUNTS), [Zoho CRM](/actionkit/integrations/zohocrm/ZOHO_CRM_SEARCH_RECORDS_ANY) |
| Page number    | For each page, add 1 to a running `pageOffset` parameter passed to `paginationParameters` in the next call.                                  | `page`, `pageNo`, `pageNumber`, or `pageOffset` | [Dropbox Sign](/actionkit/integrations/dropboxsign/DROPBOX_SIGN_SEARCH_SIGNATURE_REQUESTS), [ServiceNow](/actionkit/integrations/servicenow/SERVICENOW_GET_TICKETS), [Xero](/actionkit/integrations/xero/XERO_GET_ACCOUNTS)                |

You can find the specific pagination parameters available for each action in the [Actions Reference](/actionkit/supported-integrations). Actions that support pagination include `paginationParameters` in their input schema.

## File Uploads

Actions that accept a `file` input to upload a file to an integration (for example, [Google Drive: Save File](/actionkit/integrations/googledrive/GOOGLE_DRIVE_SAVE_FILE) and [Box: Save File](/actionkit/integrations/box/BOX_SAVE_FILE)) will need to be encoded as part of the JSON payload provided when the Action is run.

1. **Hex-encode the file**

   With the file contents you want to upload, hex-encode of the bytes file that you intend to upload.

2. **Construct a File object**

   A File object is a JSON object that represents a File to upload. You must provide three standard fields:

   ```json File object theme={null}
   {
       "dataType": "FILE", // Always set to "FILE"
       "mimeType": "text/plain", // Set to the file's known MIME type
       "data": "..." // Use the hex-encoded file data
   }
   ```

#### Examples

Here are some end-to-end examples of uploading a file with ActionKit in a few different client languages:

<CodeGroup>
  ```javascript Node.js expandable theme={null}
  import fs from 'node:fs';
  const filePath = './report.pdf';
  const fileBuffer = fs.readFileSync(filePath);

  const body = {
      action: "GOOGLE_DRIVE_SAVE_FILE",
      parameters: {
          filename: "report.pdf",
          file: {
              mimeType: "application/pdf",
              dataType: "FILE",
              data: fileBuffer.toString('hex'),
          },
      },
  };

  const res = await fetch(
      `https://actionkit.useparagon.com/projects/${PROJECT_ID}/actions`,
      {
          method: "POST",
          headers: {
              "Content-Type": "application/json",
              Authorization: `Bearer ${PARAGON_USER_TOKEN}`,
          },
          body: JSON.stringify(body),
      },
  );
  ```

  ```python Python expandable theme={null}
  from pathlib import Path
  import json
  import requests

  file_path = Path("./report.pdf")
  file_bytes = file_path.read_bytes()

  body = {
      "action": "GOOGLE_DRIVE_SAVE_FILE",
      "parameters": {
          "filename": "report.pdf",
          "file": {
              "mimeType": "application/pdf",
              "dataType": "FILE",
              "data": file_bytes.hex(),
          },
      },
  }

  res = requests.post(
      f"https://actionkit.useparagon.com/projects/{PROJECT_ID}/actions",
      headers={
          "Content-Type": "application/json",
          "Authorization": f"Bearer {PARAGON_USER_TOKEN}",
      },
      data=json.dumps(body),
  )
  ```

  ```bash Bash theme={null}
  FILE_HEX="$(xxd -p -c 1000000 "./report.pdf" | tr -d '\n')"

  curl "https://actionkit.useparagon.com/projects/${PROJECT_ID}/actions" \
      -X POST \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer ${PARAGON_USER_TOKEN}" \
      --data "$(jq -n \
          --arg data "$FILE_HEX" \
          '{
          action: "GOOGLE_DRIVE_SAVE_FILE",
          parameters: {
              filename: "report.pdf",
              file: {
              mimeType: "application/pdf",
              dataType: "FILE",
              data: $data
              }
          }
          }'
      )"
  ```
</CodeGroup>

#### Limitations

ActionKit limits incoming request body payloads to **10 MB**. Because of the required hex encoding, uploaded files are effectively limited to 5 MB.

For larger file sizes, use the [Proxy API](/apis/proxy) to upload to the integration directly.

## Using Multi-Account Authorization

[Multi-Account Authorization](/apis/api-reference/multi-account-authorization#getting-started) is a set of SDK options that enables you to connect multiple accounts of the same integration type for a [Connected User](/billing/connected-users).

You can use Multi-Account Authorization with ActionKit by specifying a credential with a header of `X-Paragon-Credential`.

```http REST API theme={null}
POST https://actionkit.useparagon.com/projects/<Project ID>/tools

Authorization: Bearer <Paragon User Token>
X-Paragon-Credential: <Credential ID>

// Body
{
    "tool": "SLACK_SEND_MESSAGE",
    "parameters": {
        "channel": "#general",
        "message": "Hello world!"
    }
}
```
