curl --request POST \
--url https://app.rubiehq.com/api/v1/credential-sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"strategy_id": "strat_NQ",
"return_url": "https://app.example.com/settings/integrations/connected"
}
'import requests
url = "https://app.rubiehq.com/api/v1/credential-sessions"
payload = {
"strategy_id": "strat_NQ",
"return_url": "https://app.example.com/settings/integrations/connected"
}
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({
strategy_id: 'strat_NQ',
return_url: 'https://app.example.com/settings/integrations/connected'
})
};
fetch('https://app.rubiehq.com/api/v1/credential-sessions', 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.rubiehq.com/api/v1/credential-sessions",
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([
'strategy_id' => 'strat_NQ',
'return_url' => 'https://app.example.com/settings/integrations/connected'
]),
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.rubiehq.com/api/v1/credential-sessions"
payload := strings.NewReader("{\n \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\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.rubiehq.com/api/v1/credential-sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.rubiehq.com/api/v1/credential-sessions")
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 \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\n}"
response = http.request(request)
puts response.read_body{
"id": "sess_MQ",
"status": "pending",
"hosted_url": "https://app.rubiehq.com/credential-collect/abc123",
"return_url": "https://app.example.com/settings/integrations/connected",
"strategy_id": "strat_NQ",
"credential_id": null,
"expires_at": "2026-08-07T17:00:00.000Z",
"completed_at": null,
"created_at": "2026-07-31T17:00:00.000Z"
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}Create credential session
Start a Rubie-hosted credential collection flow for an end user.
curl --request POST \
--url https://app.rubiehq.com/api/v1/credential-sessions \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"strategy_id": "strat_NQ",
"return_url": "https://app.example.com/settings/integrations/connected"
}
'import requests
url = "https://app.rubiehq.com/api/v1/credential-sessions"
payload = {
"strategy_id": "strat_NQ",
"return_url": "https://app.example.com/settings/integrations/connected"
}
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({
strategy_id: 'strat_NQ',
return_url: 'https://app.example.com/settings/integrations/connected'
})
};
fetch('https://app.rubiehq.com/api/v1/credential-sessions', 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.rubiehq.com/api/v1/credential-sessions",
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([
'strategy_id' => 'strat_NQ',
'return_url' => 'https://app.example.com/settings/integrations/connected'
]),
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.rubiehq.com/api/v1/credential-sessions"
payload := strings.NewReader("{\n \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\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.rubiehq.com/api/v1/credential-sessions")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.rubiehq.com/api/v1/credential-sessions")
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 \"strategy_id\": \"strat_NQ\",\n \"return_url\": \"https://app.example.com/settings/integrations/connected\"\n}"
response = http.request(request)
puts response.read_body{
"id": "sess_MQ",
"status": "pending",
"hosted_url": "https://app.rubiehq.com/credential-collect/abc123",
"return_url": "https://app.example.com/settings/integrations/connected",
"strategy_id": "strat_NQ",
"credential_id": null,
"expires_at": "2026-08-07T17:00:00.000Z",
"completed_at": null,
"created_at": "2026-07-31T17:00:00.000Z"
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}{
"error": {
"type": "authentication_error",
"message": "<string>",
"details": [
{
"message": "<string>",
"code": "<string>",
"field": "<string>"
}
]
}
}hosted_url for the end user (same-tab
redirect is typical), then either wait for their return via return_url or poll
GET /credential-sessions/{id}
until status is completed.
curl -s "$RUBIE_API_URL/api/v1/credential-sessions" \
-X POST \
-H "Authorization: Bearer $RUBIE_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: connect-account-42" \
-d '{
"strategy_id": "strat_...",
"return_url": "https://app.example.com/settings/integrations/connected"
}'
Notes
strategy_idis provisioned by Rubie for your account — one per system you connect to.return_urlis optional. If set, its origin must be allowlisted on your account. Rubie redirects there withsession_idappended; confirm the session server-side before savingcredential_id.- Credentials are validated against the target system on first Blueprint run, not when the form is submitted.
return_url handling.Authorizations
Your Rubie API key as a bearer token.
Headers
Unique key for safely retrying mutating requests. Matching key + body replays the original response for 24 hours. Matching key + different body returns 409 conflict.
Body
Provisioned authentication strategy id (strat_...).
"strat_NQ"
Optional display name for the vaulted credential shell.
256Optional URL to send the end user back to after credential collection. Its exact origin (scheme, host, and port) must be allowlisted for your account by Rubie. The redirect appends session_id; confirm the session server-side before saving credential_id.
2048"https://app.example.com/settings/integrations/connected"
Response
Session created
"sess_MQ"
Lifecycle status of the session. completed always means terminal and usable: the credential is vaulted and may be passed to a run. expired is terminal and not usable. pending means the end user has not finished the hosted form yet.
Treat this as an open string set rather than a fixed enum. Additional non-terminal statuses may be introduced between collection and completed — for example while Rubie verifies the credential against the target system. Keep polling on any status you do not recognise, and only branch on the three values above. Code written as if (status === "completed") { save(credential_id) } stays correct.
pending, completed, expired "strat_NQ"
Rubie-hosted form URL. Open for the end user while status is pending.
Customer URL supplied when the session was created. After collection, Rubie redirects here with session_id appended as a query parameter.
Present only when status is completed, and stable for the life of the credential. Retain it against your user record. Do not persist an id read from a session in any other status.
"cred_NDc"