curl --request PUT \
--url https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scopes": [
"https://www.googleapis.com/auth/calendar.readonly"
],
"connection_config": {
"subdomain": "acme-prod"
}
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}"
payload = {
"scopes": ["https://www.googleapis.com/auth/calendar.readonly"],
"connection_config": { "subdomain": "acme-prod" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
connection_config: {subdomain: 'acme-prod'}
})
};
fetch('https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}', 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://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scopes' => [
'https://www.googleapis.com/auth/calendar.readonly'
],
'connection_config' => [
'subdomain' => 'acme-prod'
]
]),
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://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}"
payload := strings.NewReader("{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}"
response = http.request(request)
puts response.read_body{
"redirect_url": "https://app.base44.com/api/external-auth/connect/3f9c2a7e5b8d4c1fa6e0d2b7c9a1e4f3",
"connection_id": "base44_6820f3a4e7b91d003c45a1f7",
"already_authorized": false,
"error": "different_user",
"error_message": "Integration googlecalendar is already authorized by a different user for this app."
}Set connector scopes
Sets the app’s connection for a connector to exactly the scopes you send, and returns a link to authorize them when that takes a new authorization.
Start connector connection adds scopes to what the app already has. This endpoint replaces them, so scopes you leave out are dropped once the new authorization completes. Scopes Base44’s OAuth app doesn’t allow for the connector are dropped without an error, and scopes the connector always needs are added.
Read already_authorized and error first:
- When you already have an active connection with exactly these scopes and connection values,
already_authorizedistrueand there’s nothing to open. Calling again changes nothing. - When another collaborator’s active connection has exactly these scopes, the call reports
different_user. To replace it with yours, use Start connector connection withforce_reconnect. - Otherwise, including when the scopes or connection values differ from another collaborator’s connection, a new authorization starts. Completing it replaces the app’s current connection.
To authorize, open redirect_url in a browser, approve the scopes within five minutes of the call, and poll Get connector connection status with connection_id until it’s ACTIVE or FAILED. The link stops working after 10 minutes. Until the authorization completes, each call starts a new one with a new link.
redirect_url as a credential. Whoever approves access through it connects their provider account to the app.The call is refused when the workspace has turned off builder connections for the connector. It works only for connectors that Base44’s OAuth app can connect: a connector_mode of all or shared_only in List connectors, with an auth_method other than platform_credentials.
This is limited to 15 requests a minute per caller. Some workspaces have a different limit.
curl --request PUT \
--url https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"scopes": [
"https://www.googleapis.com/auth/calendar.readonly"
],
"connection_config": {
"subdomain": "acme-prod"
}
}
'import requests
url = "https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}"
payload = {
"scopes": ["https://www.googleapis.com/auth/calendar.readonly"],
"connection_config": { "subdomain": "acme-prod" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
scopes: ['https://www.googleapis.com/auth/calendar.readonly'],
connection_config: {subdomain: 'acme-prod'}
})
};
fetch('https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}', 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://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'scopes' => [
'https://www.googleapis.com/auth/calendar.readonly'
],
'connection_config' => [
'subdomain' => 'acme-prod'
]
]),
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://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}"
payload := strings.NewReader("{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.base44.com/api/apps/{app_id}/external-auth/integrations/{integration_type}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"scopes\": [\n \"https://www.googleapis.com/auth/calendar.readonly\"\n ],\n \"connection_config\": {\n \"subdomain\": \"acme-prod\"\n }\n}"
response = http.request(request)
puts response.read_body{
"redirect_url": "https://app.base44.com/api/external-auth/connect/3f9c2a7e5b8d4c1fa6e0d2b7c9a1e4f3",
"connection_id": "base44_6820f3a4e7b91d003c45a1f7",
"already_authorized": false,
"error": "different_user",
"error_message": "Integration googlecalendar is already authorized by a different user for this app."
}Authorizations
Personal access token, sent as Authorization: Bearer <token>.
Path Parameters
ID of the connector, from integration_type in List connectors.
googlecalendar, google_classroom, googledrive, gmail, googlesheets, googledocs, googleslides, googlebigquery, googlemeet, googletasks, googleads, google_analytics, google_search_console, slack, notion, salesforce, hubspot, linkedin, tiktok, instagram, discord, slackbot, wix, github, gitlab, bamboohr, dropbox, clickup, wrike, box, outlook, linear, airtable, microsoft_teams, share_point, one_drive, typeform, splitwise, hugging_face, calendly, contentful, supabase, snowflake, databricks, quickbooks, square ID of the app.
Body
The scopes, and any connection values, the app's connection should have.
Every OAuth scope the connection should have. Scopes the app's current connection has and this list leaves out are dropped. Send an empty list for the connector's default scopes.
[
"https://www.googleapis.com/auth/calendar.readonly"
]
Values the connector needs before authorization, keyed by the name of each field from Get connector connection fields. Leave it out for connectors that have no fields. Values that differ from the saved ones start a new authorization.
Show child attributes
Show child attributes
{ "subdomain": "acme-prod" }
Response
The authorization was started, or the response says why none was needed.
The authorization that sets the app's connection to the requested scopes, or why none was needed.
Link to open in a browser so the user can sign in to the provider and approve the scopes. It expires after 10 minutes. Treat it as a credential. The value is null when no authorization was started.
"https://app.base44.com/api/external-auth/connect/3f9c2a7e5b8d4c1fa6e0d2b7c9a1e4f3"
ID of the connection being authorized. Pass it to Get connector connection status. When already_authorized is true it's the existing connection. The value is null when error is set.
"base44_6820f3a4e7b91d003c45a1f7"
Whether you already have an active connection with exactly these scopes and connection values (true), so there's nothing to open, or not (false).
false
Why no authorization was started, or null if one was. Either different_user, when another collaborator's active connection already has exactly these scopes, or service_unavailable, when the provider can't be reached. Retry later.
"different_user"
Readable explanation of error. It can be null even when error is set, so branch on error.
"Integration googlecalendar is already authorized by a different user for this app."
Was this page helpful?