curl --request POST \
--url https://api.erdo.ai/v1/integrations-connect \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"app": "<string>",
"credentials": {},
"managed_access": "<string>",
"name": "<string>",
"return_url": "<string>",
"rotate_credentials": true,
"scopes": [
"<string>"
],
"share_with_org": true
}
'import requests
url = "https://api.erdo.ai/v1/integrations-connect"
payload = {
"app": "<string>",
"credentials": {},
"managed_access": "<string>",
"name": "<string>",
"return_url": "<string>",
"rotate_credentials": True,
"scopes": ["<string>"],
"share_with_org": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
app: '<string>',
credentials: {},
managed_access: '<string>',
name: '<string>',
return_url: '<string>',
rotate_credentials: true,
scopes: ['<string>'],
share_with_org: true
})
};
fetch('https://api.erdo.ai/v1/integrations-connect', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.erdo.ai/v1/integrations-connect",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'app' => '<string>',
'credentials' => [
],
'managed_access' => '<string>',
'name' => '<string>',
'return_url' => '<string>',
'rotate_credentials' => true,
'scopes' => [
'<string>'
],
'share_with_org' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.erdo.ai/v1/integrations-connect"
payload := strings.NewReader("{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.erdo.ai/v1/integrations-connect")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.erdo.ai/v1/integrations-connect")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}"
response = http.request(request)
puts response.read_body{
"app": "<string>",
"connect_url": "<string>",
"integration_id": "<string>",
"next_step": "<string>",
"organization_name": "<string>",
"organization_slug": "<string>",
"status": "<string>"
}{
"code": "not_found",
"details": {},
"message": "<string>"
}ConnectIntegrationAPI mirrors the erdo_connect_integration MCP tool.
curl --request POST \
--url https://api.erdo.ai/v1/integrations-connect \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"app": "<string>",
"credentials": {},
"managed_access": "<string>",
"name": "<string>",
"return_url": "<string>",
"rotate_credentials": true,
"scopes": [
"<string>"
],
"share_with_org": true
}
'import requests
url = "https://api.erdo.ai/v1/integrations-connect"
payload = {
"app": "<string>",
"credentials": {},
"managed_access": "<string>",
"name": "<string>",
"return_url": "<string>",
"rotate_credentials": True,
"scopes": ["<string>"],
"share_with_org": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
app: '<string>',
credentials: {},
managed_access: '<string>',
name: '<string>',
return_url: '<string>',
rotate_credentials: true,
scopes: ['<string>'],
share_with_org: true
})
};
fetch('https://api.erdo.ai/v1/integrations-connect', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.erdo.ai/v1/integrations-connect",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'app' => '<string>',
'credentials' => [
],
'managed_access' => '<string>',
'name' => '<string>',
'return_url' => '<string>',
'rotate_credentials' => true,
'scopes' => [
'<string>'
],
'share_with_org' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.erdo.ai/v1/integrations-connect"
payload := strings.NewReader("{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.erdo.ai/v1/integrations-connect")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.erdo.ai/v1/integrations-connect")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"app\": \"<string>\",\n \"credentials\": {},\n \"managed_access\": \"<string>\",\n \"name\": \"<string>\",\n \"return_url\": \"<string>\",\n \"rotate_credentials\": true,\n \"scopes\": [\n \"<string>\"\n ],\n \"share_with_org\": true\n}"
response = http.request(request)
puts response.read_body{
"app": "<string>",
"connect_url": "<string>",
"integration_id": "<string>",
"next_step": "<string>",
"organization_name": "<string>",
"organization_slug": "<string>",
"status": "<string>"
}{
"code": "not_found",
"details": {},
"message": "<string>"
}Authorizations
An Erdo API key (erdo_api_...) or scoped token (erdo_token_...).
Body
service-account JSON). encore:"sensitive" keeps it out of request trace storage — the same treatment integration.CreateIntegrationRequest.Credentials gets.
Show child attributes
Show child attributes
manages. It is honoured only on the native credential path: a Pipedream connection is not an integration row this column lives on, and an OAuth grant is a named person's account at the provider, which is never something to spend on another business's behalf. Both are refused rather than ignored — a caller who asked for lending and got silence would believe its clients could use the key.
It carries no jsonschema tag and handleConnectIntegration clears it before the logic runs, so no MCP caller can set it whatever the schema generator does with an untagged field: widening which organizations a credential serves is not a decision a model should be able to take, the same reasoning that keeps manager-key minting off MCP.
authorization at connect_url. Only meaningful for OAuth apps (native OAuth and Pipedream) that hand back a connect_url. Empty returns the user to Erdo's data page — the default for MCP/CLI callers with no product origin of their own; a portal built on /v1 passes its own page so the operator lands back on it. Must be an absolute http(s) URL with no embedded credentials.
instead of adding a second one. A rotated key must land on the connection everything else already references — a sibling connection leaves every pinned widget, automation and shared grant pointing at the dead key.
instead of the default private-to-the-connector. A credential connected headlessly is usually org infrastructure (a customer org's calendar, a shared SaaS key) that teammates and org agents must be able to see and build on — private-by-default is right for a personal OAuth grant, wrong for that.

