curl --request POST \
--url https://api.maxcare.ai/v1/marketplace/verify-session \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sessionToken": "eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ..."
}
'import requests
url = "https://api.maxcare.ai/v1/marketplace/verify-session"
payload = { "sessionToken": "eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ..." }
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({
sessionToken: 'eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...'
})
};
fetch('https://api.maxcare.ai/v1/marketplace/verify-session', 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.maxcare.ai/v1/marketplace/verify-session",
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([
'sessionToken' => 'eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...'
]),
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.maxcare.ai/v1/marketplace/verify-session"
payload := strings.NewReader("{\n \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\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.maxcare.ai/v1/marketplace/verify-session")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.maxcare.ai/v1/marketplace/verify-session")
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 \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\n}"
response = http.request(request)
puts response.read_body{
"code": "success",
"data": {
"organizationId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"clerkOrganizationId": "org_38dgm0BKetZbaGtOlbsPxr2HheD",
"clerkUserId": "user_36uZihkXH7t0iB5RWRTbhPh1N2W",
"installationId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
}
}{
"code": "unauthorized",
"message": "Invalid or missing API key",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 1000 requests per 60 seconds.",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}Verify a session token and resolve its organization
Takes the app-scoped token the App Bridge handed your iframe and returns the Max AI organization it belongs to, but only if your app has an ACTIVE installation for that organization. Use this instead of trusting X-Organization-Id, which is iframe metadata rather than proof, and instead of verifying the JWT yourself — the ways to get that subtly wrong (trusting the token’s own iss, accepting alg: none) are authentication bypasses. Returns 401 for an invalid token, a token with no active organization, or an organization your app is not installed for; the three are deliberately not distinguished in the response.
curl --request POST \
--url https://api.maxcare.ai/v1/marketplace/verify-session \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"sessionToken": "eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ..."
}
'import requests
url = "https://api.maxcare.ai/v1/marketplace/verify-session"
payload = { "sessionToken": "eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ..." }
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({
sessionToken: 'eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...'
})
};
fetch('https://api.maxcare.ai/v1/marketplace/verify-session', 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.maxcare.ai/v1/marketplace/verify-session",
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([
'sessionToken' => 'eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...'
]),
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.maxcare.ai/v1/marketplace/verify-session"
payload := strings.NewReader("{\n \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\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.maxcare.ai/v1/marketplace/verify-session")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.maxcare.ai/v1/marketplace/verify-session")
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 \"sessionToken\": \"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ...\"\n}"
response = http.request(request)
puts response.read_body{
"code": "success",
"data": {
"organizationId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"clerkOrganizationId": "org_38dgm0BKetZbaGtOlbsPxr2HheD",
"clerkUserId": "user_36uZihkXH7t0iB5RWRTbhPh1N2W",
"installationId": "b1c2d3e4-f5a6-4b7c-8d9e-0f1a2b3c4d5e"
}
}{
"code": "unauthorized",
"message": "Invalid or missing API key",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}{
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Maximum 1000 requests per 60 seconds.",
"trace_id": "550e8400-e29b-41d4-a716-446655440000"
}Authorizations
Marketplace API key
Body
The app-scoped token the App Bridge handed your iframe — maxcare.appToken(), or the auth:token-request reply. Named sessionToken for wire compatibility; a Clerk session token is not accepted here, and the platform no longer issues one to embedded apps.
"eyJhbGciOiJFUzI1NiIsImtpZCI6InlQOVBQb095dURFNnVKVXNYYlo3TmZKck41M21xM1I1blJtTFBEdk4zWlUifQ..."
