---
title: Quickstart
description: Make your first MindCloud Universal API request in minutes with one REST shape across 3,400+ apps.
---

This is the fastest path to a working request against any connected app. The request shape is identical across every app on the Universal API, so what you learn here applies everywhere.

## Before you start

You need three things:

1. A **MindCloud account**. Sign in at <DocsQuickstartTrackedLink eventName="docs_quickstart_account_click" href="https://app.mindcloud.co">MindCloud</DocsQuickstartTrackedLink>.
2. A **MindCloud API Key**. Create one in <DocsQuickstartTrackedLink eventName="docs_quickstart_api_key_click" href="https://app.mindcloud.co/user/api-keys">API Keys</DocsQuickstartTrackedLink>. Keep it on your server.
3. At least one **app connection**. Create or choose one in <DocsQuickstartTrackedLink eventName="docs_quickstart_connection_click" href="https://app.mindcloud.co/credentials">Connections</DocsQuickstartTrackedLink>. Note its `connectionId`.

## Make your first request

Every action request uses the same URL pattern:

```text
POST https://connect.mindcloud.co/v2/universal/apps/{appSlug}/actions/{actionSlug}/run
```

Authenticate with your MindCloud API Key as a Bearer token. Pass action arguments inside the `arguments` object.

```bash
curl --request POST "https://connect.mindcloud.co/v2/universal/apps/hubspot/actions/list-users/run" \
  --header "Authorization: Bearer $MINDCLOUD_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{"connectionId": "'"$CONNECTION_ID"'", "arguments": {"limit": 10}}'
```

You can omit `connectionId` when the app has a default connection.

## What you get back

The Universal API returns the same envelope for every app — `success`, your `data`, and optional `meta`. The `list-users` call above comes back like this:

```json
{
  "success": true,
  "data": [
    { "id": "U123", "name": "Ava" },
    { "id": "U456", "name": "Ben" }
  ]
}
```

`data` is always an array — even for actions that return a single record — so your code reads every app's response the same way.

## Uploading files

For larger uploads, pass a temporary download URL in the action's file argument. Keep the URL valid and accessible until the request finishes. The JSON request-body limit is separate from the file-size limit; embedding a large base64 string does not bypass it.

Files default to a maximum of **100 MB** (100,000,000 bytes). An app's explicit file limit takes precedence, including an existing larger limit. All files in one action share an aggregate allowance equal to the larger of 100 MB or the action's largest explicit file limit. The destination provider can impose additional limits.

File transfers can run for up to **10 minutes**, including downloading the source and uploading it. A transfer stops after **2 minutes without byte progress**, or if the provider takes more than 2 minutes to confirm completion after upload. Configure your HTTP client's timeout to allow the full operation.

If you receive a timeout, cancellation or connection error after sending starts, the destination may already have saved the file. Check there before retrying to avoid duplicates. Cancelling the request does not delete a file already saved by the provider.

## What to read next

- [Browse apps](./browse-apps) to find the app you want and open its actions.
- Pick an app, then read its **Authentication** and **Arguments** pages for the specifics of that app.
