Record a consent decision
curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/consent \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"request_id": "areq_3b2a...",
"csrf_token": "csrf_7f1e...",
"company_id": "Dsc8SfHtPjzNGDKzMqBP",
"decision": "allow",
"granted_scopes": [
"campaigns:read",
"contracts:read",
"offline_access"
]
}
'import requests
url = "https://app.sideshift.app/api/oauth/v1/consent"
payload = {
"request_id": "areq_3b2a...",
"csrf_token": "csrf_7f1e...",
"company_id": "Dsc8SfHtPjzNGDKzMqBP",
"decision": "allow",
"granted_scopes": ["campaigns:read", "contracts:read", "offline_access"]
}
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({
request_id: 'areq_3b2a...',
csrf_token: 'csrf_7f1e...',
company_id: 'Dsc8SfHtPjzNGDKzMqBP',
decision: 'allow',
granted_scopes: ['campaigns:read', 'contracts:read', 'offline_access']
})
};
fetch('https://app.sideshift.app/api/oauth/v1/consent', 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.sideshift.app/api/oauth/v1/consent",
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([
'request_id' => 'areq_3b2a...',
'csrf_token' => 'csrf_7f1e...',
'company_id' => 'Dsc8SfHtPjzNGDKzMqBP',
'decision' => 'allow',
'granted_scopes' => [
'campaigns:read',
'contracts:read',
'offline_access'
]
]),
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.sideshift.app/api/oauth/v1/consent"
payload := strings.NewReader("{\n \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\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://app.sideshift.app/api/oauth/v1/consent")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/oauth/v1/consent")
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 \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"redirect": "https://acme.example.com/oauth/callback?code=ac_...&state=xyz987&iss=https://app.sideshift.app",
"decision": "allow"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}Record a consent decision
Records the user’s allow/deny decision for the chosen company tenant, mints the authorization code on allow, and returns the redirect target. CSRF token and the selected company are validated. Subscription and capability restrictions are enforced when the issued token calls a resource.
POST
/
consent
Record a consent decision
curl --request POST \
--url https://app.sideshift.app/api/oauth/v1/consent \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"request_id": "areq_3b2a...",
"csrf_token": "csrf_7f1e...",
"company_id": "Dsc8SfHtPjzNGDKzMqBP",
"decision": "allow",
"granted_scopes": [
"campaigns:read",
"contracts:read",
"offline_access"
]
}
'import requests
url = "https://app.sideshift.app/api/oauth/v1/consent"
payload = {
"request_id": "areq_3b2a...",
"csrf_token": "csrf_7f1e...",
"company_id": "Dsc8SfHtPjzNGDKzMqBP",
"decision": "allow",
"granted_scopes": ["campaigns:read", "contracts:read", "offline_access"]
}
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({
request_id: 'areq_3b2a...',
csrf_token: 'csrf_7f1e...',
company_id: 'Dsc8SfHtPjzNGDKzMqBP',
decision: 'allow',
granted_scopes: ['campaigns:read', 'contracts:read', 'offline_access']
})
};
fetch('https://app.sideshift.app/api/oauth/v1/consent', 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.sideshift.app/api/oauth/v1/consent",
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([
'request_id' => 'areq_3b2a...',
'csrf_token' => 'csrf_7f1e...',
'company_id' => 'Dsc8SfHtPjzNGDKzMqBP',
'decision' => 'allow',
'granted_scopes' => [
'campaigns:read',
'contracts:read',
'offline_access'
]
]),
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.sideshift.app/api/oauth/v1/consent"
payload := strings.NewReader("{\n \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\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://app.sideshift.app/api/oauth/v1/consent")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.sideshift.app/api/oauth/v1/consent")
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 \"request_id\": \"areq_3b2a...\",\n \"csrf_token\": \"csrf_7f1e...\",\n \"company_id\": \"Dsc8SfHtPjzNGDKzMqBP\",\n \"decision\": \"allow\",\n \"granted_scopes\": [\n \"campaigns:read\",\n \"contracts:read\",\n \"offline_access\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"redirect": "https://acme.example.com/oauth/callback?code=ac_...&state=xyz987&iss=https://app.sideshift.app",
"decision": "allow"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}{
"error": "expired",
"message": "This authorization request has expired"
}Authorizations
The end-user's Firebase session token. Used only by the in-session consent endpoints (/consent), which run inside the SideShift web app.
Body
application/json
Available options:
allow, deny The default tenant. Required when allowing access.
Optional explicit accounts to connect, with no count limit. Must include company_id. Each account is access-checked and gets its own revocable grant. Omit for a single account.
Minimum array length:
1Required string length:
1 - 128Subset of the requested scopes the user approved (allow only).