curl --request POST \
--url https://api.withampersand.com/v1/custom-auth/connect \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"projectIdOrName": "my-project",
"provider": "bill",
"groupRef": "group-123",
"groupName": "Organization Name",
"consumerRef": "user_123456",
"consumerName": "John Doe",
"providerMetadata": {},
"providerAppId": "32356abe-d2fd-49c7-9030-abdcbc6456d4",
"customAuth": {
"userName": "admin@acme.com",
"password": "hunter2"
},
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d",
"callbackParams": {
"tenant": "9e1477fd-54ef-41fe-b747-bc9e6a11a925"
}
}
'import requests
url = "https://api.withampersand.com/v1/custom-auth/connect"
payload = {
"projectIdOrName": "my-project",
"provider": "bill",
"groupRef": "group-123",
"groupName": "Organization Name",
"consumerRef": "user_123456",
"consumerName": "John Doe",
"providerMetadata": {},
"providerAppId": "32356abe-d2fd-49c7-9030-abdcbc6456d4",
"customAuth": {
"userName": "admin@acme.com",
"password": "hunter2"
},
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d",
"callbackParams": { "tenant": "9e1477fd-54ef-41fe-b747-bc9e6a11a925" }
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectIdOrName: 'my-project',
provider: 'bill',
groupRef: 'group-123',
groupName: 'Organization Name',
consumerRef: 'user_123456',
consumerName: 'John Doe',
providerMetadata: {},
providerAppId: '32356abe-d2fd-49c7-9030-abdcbc6456d4',
customAuth: {userName: 'admin@acme.com', password: 'hunter2'},
sessionId: '7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d',
callbackParams: {tenant: '9e1477fd-54ef-41fe-b747-bc9e6a11a925'}
})
};
fetch('https://api.withampersand.com/v1/custom-auth/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.withampersand.com/v1/custom-auth/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([
'projectIdOrName' => 'my-project',
'provider' => 'bill',
'groupRef' => 'group-123',
'groupName' => 'Organization Name',
'consumerRef' => 'user_123456',
'consumerName' => 'John Doe',
'providerMetadata' => [
],
'providerAppId' => '32356abe-d2fd-49c7-9030-abdcbc6456d4',
'customAuth' => [
'userName' => 'admin@acme.com',
'password' => 'hunter2'
],
'sessionId' => '7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d',
'callbackParams' => [
'tenant' => '9e1477fd-54ef-41fe-b747-bc9e6a11a925'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>"
],
]);
$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.withampersand.com/v1/custom-auth/connect"
payload := strings.NewReader("{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
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.withampersand.com/v1/custom-auth/connect")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.withampersand.com/v1/custom-auth/connect")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}"
response = http.request(request)
puts response.read_body{
"redirect": {
"url": "https://login.microsoftonline.com/common/adminconsent?client_id=xxx",
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d"
}
}{
"type": "about:blank",
"href": "https://www.belgif.be/specification/rest/api-guide/#standardized-problem-types",
"title": "Bad Request",
"status": 400,
"detail": "The input message is incorrect",
"instance": "123456-1234-1235-4567489798",
"issues": [
{
"type": "about:blank",
"detail": "exampleNumericProperty should be numeric",
"in": "path",
"name": "exampleNumericProperty",
"value": "abc"
},
{
"type": "about:blank",
"title": "Input isn't valid with respect to schema",
"detail": "examplePropertyWithPattern a2345678901 doesn't match pattern '^\\d{11}$'",
"in": "body",
"name": "items[0].examplePropertyWithPattern",
"value": "a2345678901"
}
]
}{
"type": "urn:problem-type:exampleOrganization:exampleProblem",
"href": "https://www.belgif.be/specification/rest/api-guide/#standardized-problem-types",
"title": "Description of the type of problem that occurred",
"status": 400,
"detail": "Description of specific occurrence of the problem",
"instance": "urn:uuid:123e4567-e89b-12d3-a456-426614174000"
}Start or continue a multi-step custom auth flow
Drives a multi-step custom auth flow (browser redirects and/or server-side credential-exchange calls). Call it once with the flow inputs to start; if the response contains a redirect, open it, then call again with the returned sessionId and the provider’s callback params to continue. Repeat until the response contains a connection. Used by the prebuilt UI components; only providers whose ProviderInfo has customOpts.multiStep present can use this endpoint.
curl --request POST \
--url https://api.withampersand.com/v1/custom-auth/connect \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <api-key>' \
--data '
{
"projectIdOrName": "my-project",
"provider": "bill",
"groupRef": "group-123",
"groupName": "Organization Name",
"consumerRef": "user_123456",
"consumerName": "John Doe",
"providerMetadata": {},
"providerAppId": "32356abe-d2fd-49c7-9030-abdcbc6456d4",
"customAuth": {
"userName": "admin@acme.com",
"password": "hunter2"
},
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d",
"callbackParams": {
"tenant": "9e1477fd-54ef-41fe-b747-bc9e6a11a925"
}
}
'import requests
url = "https://api.withampersand.com/v1/custom-auth/connect"
payload = {
"projectIdOrName": "my-project",
"provider": "bill",
"groupRef": "group-123",
"groupName": "Organization Name",
"consumerRef": "user_123456",
"consumerName": "John Doe",
"providerMetadata": {},
"providerAppId": "32356abe-d2fd-49c7-9030-abdcbc6456d4",
"customAuth": {
"userName": "admin@acme.com",
"password": "hunter2"
},
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d",
"callbackParams": { "tenant": "9e1477fd-54ef-41fe-b747-bc9e6a11a925" }
}
headers = {
"X-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectIdOrName: 'my-project',
provider: 'bill',
groupRef: 'group-123',
groupName: 'Organization Name',
consumerRef: 'user_123456',
consumerName: 'John Doe',
providerMetadata: {},
providerAppId: '32356abe-d2fd-49c7-9030-abdcbc6456d4',
customAuth: {userName: 'admin@acme.com', password: 'hunter2'},
sessionId: '7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d',
callbackParams: {tenant: '9e1477fd-54ef-41fe-b747-bc9e6a11a925'}
})
};
fetch('https://api.withampersand.com/v1/custom-auth/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.withampersand.com/v1/custom-auth/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([
'projectIdOrName' => 'my-project',
'provider' => 'bill',
'groupRef' => 'group-123',
'groupName' => 'Organization Name',
'consumerRef' => 'user_123456',
'consumerName' => 'John Doe',
'providerMetadata' => [
],
'providerAppId' => '32356abe-d2fd-49c7-9030-abdcbc6456d4',
'customAuth' => [
'userName' => 'admin@acme.com',
'password' => 'hunter2'
],
'sessionId' => '7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d',
'callbackParams' => [
'tenant' => '9e1477fd-54ef-41fe-b747-bc9e6a11a925'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Api-Key: <api-key>"
],
]);
$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.withampersand.com/v1/custom-auth/connect"
payload := strings.NewReader("{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-Api-Key", "<api-key>")
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.withampersand.com/v1/custom-auth/connect")
.header("X-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.withampersand.com/v1/custom-auth/connect")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"projectIdOrName\": \"my-project\",\n \"provider\": \"bill\",\n \"groupRef\": \"group-123\",\n \"groupName\": \"Organization Name\",\n \"consumerRef\": \"user_123456\",\n \"consumerName\": \"John Doe\",\n \"providerMetadata\": {},\n \"providerAppId\": \"32356abe-d2fd-49c7-9030-abdcbc6456d4\",\n \"customAuth\": {\n \"userName\": \"admin@acme.com\",\n \"password\": \"hunter2\"\n },\n \"sessionId\": \"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d\",\n \"callbackParams\": {\n \"tenant\": \"9e1477fd-54ef-41fe-b747-bc9e6a11a925\"\n }\n}"
response = http.request(request)
puts response.read_body{
"redirect": {
"url": "https://login.microsoftonline.com/common/adminconsent?client_id=xxx",
"sessionId": "7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d"
}
}{
"type": "about:blank",
"href": "https://www.belgif.be/specification/rest/api-guide/#standardized-problem-types",
"title": "Bad Request",
"status": 400,
"detail": "The input message is incorrect",
"instance": "123456-1234-1235-4567489798",
"issues": [
{
"type": "about:blank",
"detail": "exampleNumericProperty should be numeric",
"in": "path",
"name": "exampleNumericProperty",
"value": "abc"
},
{
"type": "about:blank",
"title": "Input isn't valid with respect to schema",
"detail": "examplePropertyWithPattern a2345678901 doesn't match pattern '^\\d{11}$'",
"in": "body",
"name": "items[0].examplePropertyWithPattern",
"value": "a2345678901"
}
]
}{
"type": "urn:problem-type:exampleOrganization:exampleProblem",
"href": "https://www.belgif.be/specification/rest/api-guide/#standardized-problem-types",
"title": "Description of the type of problem that occurred",
"status": 400,
"detail": "Description of specific occurrence of the problem",
"instance": "urn:uuid:123e4567-e89b-12d3-a456-426614174000"
}Authorizations
Body
Request body for the /custom-auth/connect endpoint. The first call supplies the flow inputs; subsequent calls supply sessionId and callbackParams to resume after a redirect.
The Ampersand project ID or project name. Required on the first call.
"my-project"
The provider that this app connects to. Required on the first call (when sessionId is not present); ignored on resume calls. Conditional requirement is enforced at the application layer.
"bill"
Your application's identifier for the organization or workspace that this connection belongs to. Supplied on the first call; ignored on resume calls (the parked flow's identity is used).
"group-123"
The display name for the group. Defaults to groupRef if not provided. Supplied on the first call; ignored on resume calls.
"Organization Name"
The ID that your app uses to identify the user whose SaaS credential will be used. Supplied on the first call; ignored on resume calls (the parked flow's identity is used).
"user_123456"
The display name for the consumer. Defaults to consumerRef if not provided. Supplied on the first call; ignored on resume calls.
"John Doe"
Additional provider-specific metadata collected from the user.
Show child attributes
Show child attributes
ID of the provider app. If omitted, the default provider app set up on the Dashboard is assumed.
"32356abe-d2fd-49c7-9030-abdcbc6456d4"
The consumer-supplied custom auth inputs (keyed by CustomAuthInput.name). Supplied on the first call (when sessionId is not present).
{
"userName": "admin@acme.com",
"password": "hunter2"
}
Identifies an in-progress flow to resume after a redirect. Returned in a prior redirect response. When present, provider and customAuth are not required.
"7f3c1e2a-9b0d-4a1f-8c2e-1d2f3a4b5c6d"
The query/body params the provider sent to the callback, forwarded to resume the flow.
Show child attributes
Show child attributes
{
"tenant": "9e1477fd-54ef-41fe-b747-bc9e6a11a925"
}
Response
OK
- Custom Auth Connect Response
- Custom Auth Connect Response
Response from /custom-auth/connect. Exactly one of redirect or connection is set. A redirect means the client should open the URL and call again with sessionId + callbackParams; a connection means the flow is complete.
Instructs the client to open a URL (e.g. in a popup) to continue a custom auth flow, then resume by calling /custom-auth/connect with the sessionId.
Show child attributes
Show child attributes
Was this page helpful?

