Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 148 additions & 0 deletions docs/integrations/app-integrations/rest-api.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
---
title: REST API
sidebarTitle: REST API
---

In this section, we present how to connect any REST API to MindsDB using bearer-token authentication.

The REST API handler is a generic integration that lets you forward HTTP requests to any API through MindsDB using stored credentials. Unlike named integrations (HubSpot, Shopify, etc.), it requires no handler-specific knowledge — just a base URL and a bearer token.

This is useful for APIs that MindsDB doesn't have a dedicated handler for, or when you only need direct HTTP access without SQL table mapping.

## Connection

The required arguments to establish a connection are as follows:

- `base_url`: the base URL of the REST API (e.g. `https://api.example.com`). All request paths are appended to this URL.
- `bearer_token`: the token used for authentication. Injected as `Authorization: Bearer <token>` on every request.

Optional arguments:

- `default_headers`: a JSON object of static headers added to every request (e.g. `{"Accept": "application/json"}`).
- `allowed_hosts`: a list of allowed hostnames for requests. Defaults to the hostname of `base_url`. Use `["*"]` to disable host containment.
- `test_path`: the path used by the test endpoint to verify connectivity. Defaults to `/`.

To connect a REST API to MindsDB, create a new database:

```sql
CREATE DATABASE my_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.example.com",
"bearer_token": "your_token_here"
};
```

### Example: Connect to HubSpot

```sql
CREATE DATABASE my_hubspot
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.hubapi.com",
"bearer_token": "pat-eu1-..."
};
```

### Example: Connect with default headers and a custom test path

```sql
CREATE DATABASE my_internal_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://internal.example.com/api/v2",
"bearer_token": "sk-...",
"default_headers": {"Accept": "application/json"},
"test_path": "/health"
};
```

### Example: Multiple allowed hosts

```sql
CREATE DATABASE my_multi_region_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.example.com",
"bearer_token": "your_token",
"allowed_hosts": ["api.example.com", "api.eu.example.com"]
};
```

## Usage

This handler is **passthrough-only** — it does not expose SQL tables. All interaction is through the REST passthrough endpoint.

### Sending requests

Forward HTTP requests to the upstream API:

```
POST /api/integrations/my_api/passthrough
```

```json
{
"method": "GET",
"path": "/v1/users",
"query": {"limit": "10"},
"headers": {"Accept": "application/json"}
}
```

The response wraps the upstream HTTP response:

```json
{
"status_code": 200,
"headers": {"content-type": "application/json"},
"body": {"results": [...]},
"content_type": "application/json"
}
```

Supported HTTP methods: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`.

### Testing the connection

Verify that the base URL, token, and host allowlist are configured correctly:

```
POST /api/integrations/my_api/passthrough/test
```

A successful response:

```json
{"ok": true, "status_code": 200, "host": "api.example.com", "latency_ms": 140}
```

A failed response:

```json
{"ok": false, "error_code": "auth_failed", "message": "upstream rejected credentials; base URL and allowlist look correct"}
```

## Security

- Credentials are stored in MindsDB and never exposed to the caller.
- Requests are restricted to hostnames in the allowlist. Private and loopback IP addresses are rejected by default.
- Callers cannot override `Authorization`, `Host`, `Cookie`, or `Proxy-*` headers.
- If the upstream API echoes the token in responses, it is replaced with `[REDACTED_API_KEY]`.
- Request bodies are capped at 1 MB, response bodies at 10 MB.

<Warning>
**`host 'X' is not in the datasource allowlist`**

The request path resolved to a different hostname than `base_url`. Add the hostname to `allowed_hosts`, or use `["*"]` to disable host containment (not recommended for production).
</Warning>

<Warning>
**`upstream rejected credentials (401/403)`**

The token is invalid, expired, or missing required scopes. Verify the token with the upstream API provider.
</Warning>

<Info>
For more information about available actions and development plans, visit [this page](https://github.com/mindsdb/mindsdb/blob/main/mindsdb/integrations/handlers/rest_api_handler/README.md).
</Info>
168 changes: 168 additions & 0 deletions mindsdb/integrations/handlers/rest_api_handler/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
---
title: REST API
sidebarTitle: REST API
---

This documentation describes the integration of MindsDB with generic REST APIs using bearer-token authentication.
The integration allows MindsDB to forward HTTP requests to any REST API using stored credentials via the passthrough endpoint — no SQL table mapping required.

### Prerequisites

Before proceeding, ensure the following prerequisites are met:

1. Install MindsDB locally via [Docker](https://docs.mindsdb.com/setup/self-hosted/docker) or [Docker Desktop](https://docs.mindsdb.com/setup/self-hosted/docker-desktop).
2. Obtain a bearer token (API key, personal access token, etc.) for the target REST API.

## Connection

Establish a connection to a REST API from MindsDB by executing the following SQL command:

```sql
CREATE DATABASE my_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.example.com",
"bearer_token": "your_token_here"
};
```

Required connection parameters include the following:

* `base_url`: The base URL of the REST API (e.g. `https://api.example.com`). All passthrough request paths are appended to this URL.
* `bearer_token`: The bearer token used for authentication. Injected as `Authorization: Bearer <token>` on every request.

Optional connection parameters include the following:

* `default_headers`: A JSON object of static headers added to every request (e.g. `{"Accept": "application/json"}`).
* `allowed_hosts`: A list of allowed hostnames for passthrough requests. Defaults to the hostname of `base_url`. Use `["*"]` to disable host containment.
* `test_path`: The path used by the `/passthrough/test` endpoint to verify connectivity. Defaults to `/`.

### Examples

Connect to the HubSpot API:

```sql
CREATE DATABASE my_hubspot
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.hubapi.com",
"bearer_token": "pat-eu1-..."
};
```

Connect to a custom internal API with default headers:

```sql
CREATE DATABASE my_internal_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://internal.example.com/api/v2",
"bearer_token": "sk-...",
"default_headers": {"Accept": "application/json", "X-Team": "data"},
"test_path": "/health"
};
```

Connect to an API with multiple allowed hosts:

```sql
CREATE DATABASE my_multi_region_api
WITH ENGINE = 'rest_api',
PARAMETERS = {
"base_url": "https://api.example.com",
"bearer_token": "your_token",
"allowed_hosts": ["api.example.com", "api.eu.example.com"]
};
```

## Usage

This handler is **passthrough-only** — it does not expose SQL tables. All interaction is through the REST passthrough endpoint.

### Passthrough Requests

Send HTTP requests to the upstream API through MindsDB:

```
POST /api/integrations/my_api/passthrough
```

```json
{
"method": "GET",
"path": "/v1/users",
"query": {"limit": "10"},
"headers": {"Accept": "application/json"}
}
```

The response wraps the upstream HTTP response:

```json
{
"status_code": 200,
"headers": {"content-type": "application/json"},
"body": {"results": [...]},
"content_type": "application/json"
}
```

Supported HTTP methods: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`.

### Testing the Connection

Verify that the base URL, token, and host allowlist are configured correctly:

```
POST /api/integrations/my_api/passthrough/test
```

Returns:

```json
{"ok": true, "status_code": 200, "host": "api.example.com", "latency_ms": 140}
```

Or on failure:

```json
{"ok": false, "error_code": "auth_failed", "message": "upstream rejected credentials; base URL and allowlist look correct"}
```

## Security

- **Credentials are never exposed.** The bearer token is stored in MindsDB and injected at request time. It is never returned to the caller.
- **Host containment.** Requests are restricted to hostnames in the allowlist (defaults to the `base_url` host). Private/loopback IP addresses are rejected by default.
- **Header filtering.** Callers cannot override `Authorization`, `Host`, `Cookie`, or `Proxy-*` headers.
- **Response scrubbing.** If the upstream API echoes the token in responses, it is replaced with `[REDACTED_API_KEY]` before returning to the caller.
- **Size limits.** Request bodies are capped at 1 MB, response bodies at 10 MB (configurable via environment variables).

## Troubleshooting

<Warning>
`base_url is not configured`

* **Symptoms**: Passthrough requests fail with a configuration error.
* **Checklist**:
1. Ensure `base_url` is provided in the connection parameters.
2. The URL must include the scheme (`https://`).
</Warning>

<Warning>
`host 'X' is not in the datasource allowlist`

* **Symptoms**: Passthrough requests to a valid URL are rejected.
* **Checklist**:
1. The request path may resolve to a different hostname than `base_url`.
2. Add the hostname to `allowed_hosts` in the connection parameters.
3. Use `["*"]` to disable host containment (not recommended for production).
</Warning>

<Warning>
`upstream rejected credentials (401/403)`

* **Symptoms**: The `/passthrough/test` endpoint returns `error_code: "auth_failed"`.
* **Checklist**:
1. Verify the bearer token is valid and not expired.
2. Check that the token has the required scopes/permissions for the API endpoints you are calling.
</Warning>
9 changes: 9 additions & 0 deletions mindsdb/integrations/handlers/rest_api_handler/__about__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
__title__ = "MindsDB REST API handler"
__package_name__ = "mindsdb_rest_api_handler"
__version__ = "0.0.1"
__description__ = "MindsDB handler for generic REST APIs with bearer-token passthrough"
__author__ = "MindsDB Inc"
__github__ = "https://github.com/mindsdb/mindsdb"
__pypi__ = "https://pypi.org/project/mindsdb/"
__license__ = "MIT"
__copyright__ = "Copyright 2026 - mindsdb"
32 changes: 32 additions & 0 deletions mindsdb/integrations/handlers/rest_api_handler/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from mindsdb.integrations.libs.const import HANDLER_TYPE, HANDLER_SUPPORT_LEVEL

from .__about__ import __version__ as version, __description__ as description
from .connection_args import connection_args, connection_args_example

try:
from .rest_api_handler import RestApiHandler as Handler

import_error = None
except Exception as e:
Handler = None
import_error = e

title = "REST API"
name = "rest_api"
type = HANDLER_TYPE.DATA
icon_path = "icon.svg"
support_level = HANDLER_SUPPORT_LEVEL.MINDSDB

__all__ = [
"Handler",
"version",
"name",
"type",
"support_level",
"title",
"description",
"import_error",
"icon_path",
"connection_args",
"connection_args_example",
]
Loading
Loading