Verify External User
curl --request POST \
--url https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"userJwt": "<string>"
}
'import requests
url = "https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user"
payload = { "userJwt": "<string>" }
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({userJwt: '<string>'})
};
fetch('https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user', 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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user",
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([
'userJwt' => '<string>'
]),
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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user"
payload := strings.NewReader("{\n \"userJwt\": \"<string>\"\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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"userJwt\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user")
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 \"userJwt\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"accessToken": "<string>",
"refreshToken": "<string>",
"user": {
"id": "<string>",
"foreignId": {},
"role": "<string>",
"email": {},
"name": {},
"username": {},
"avatar": {},
"bio": {},
"metadata": {},
"reputation": {},
"isVerified": {},
"isActive": {},
"lastActive": {},
"suspensions": [
{}
],
"avatarFile": {},
"bannerFile": {},
"authMethods": [
"<string>"
],
"createdAt": "<string>"
}
}Auth Endpoints
Verify External User
Verify or create a user from an external auth system JWT
Verify External User
curl --request POST \
--url https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"userJwt": "<string>"
}
'import requests
url = "https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user"
payload = { "userJwt": "<string>" }
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({userJwt: '<string>'})
};
fetch('https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user', 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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user",
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([
'userJwt' => '<string>'
]),
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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user"
payload := strings.NewReader("{\n \"userJwt\": \"<string>\"\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.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"userJwt\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.sublay.io/api/v6/:projectId/api/v7/auth/verify-external-user")
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 \"userJwt\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"accessToken": "<string>",
"refreshToken": "<string>",
"user": {
"id": "<string>",
"foreignId": {},
"role": "<string>",
"email": {},
"name": {},
"username": {},
"avatar": {},
"bio": {},
"metadata": {},
"reputation": {},
"isVerified": {},
"isActive": {},
"lastActive": {},
"suspensions": [
{}
],
"avatarFile": {},
"bannerFile": {},
"authMethods": [
"<string>"
],
"createdAt": "<string>"
}
}Accepts a JWT signed by your own auth system and returns Sublay tokens. If the user does not exist in the project, they are created. If they do exist, their profile is updated with any changed fields from the JWT payload.
The JWT must be signed with the RSA private key corresponding to the public key configured in your Sublay project settings.
The project does not have a public key configured.
The JWT signature is invalid or the token is expired.
The
Body Parameters
string
required
A JWT signed with your project’s RSA private key (RS256 algorithm). The
payload must include
sub (external user ID) and iss (your Sublay project
ID). The userData claim may contain optional profile fields.JWT Payload Structure
TheuserJwt must contain:
| Claim | Required | Description |
|---|---|---|
sub | Yes | External user ID. Stored as foreignId on the Sublay user. |
iss | Yes | Your Sublay project ID. Must match the request project. |
userData | No | Object with optional profile fields (see below). |
userData fields
| Field | Type | Description |
|---|---|---|
email | string | Email address |
name | string | Display name |
username | string | Username |
avatar | string | Avatar URL |
bio | string | Bio text |
location | object | { latitude, longitude } |
birthdate | string | ISO 8601 date |
metadata | object | Public custom data |
secureMetadata | object | Private custom data |
Response
boolean
true on success.string
Short-lived JWT access token. Expires in 30 minutes.
string
Long-lived JWT refresh token. Expires in 30 days.
object
The verified or created user’s profile.
Show properties
Show properties
string
Unique user ID (UUID).
string | null
External user ID (the
sub claim).string
User role.
string | null
Email address.
string | null
Display name.
string | null
Username.
string | null
Avatar URL.
string | null
Bio text.
object | null
Public custom data.
number | null
Reputation score.
boolean | null
Whether the user is verified.
boolean | null
Whether the account is active.
string | null
ISO timestamp of last activity.
array
Active suspensions on the account.
object | null
Processed avatar file with variants.
object | null
Processed banner file with variants.
string[]
List of auth methods (includes
"external").string
ISO timestamp of account creation.
Error Responses
Missing JWT Keys — 403
Missing JWT Keys — 403
{
"error": "Missing JWT keys",
"code": "auth/missing-keys"
}
Invalid Token — 403
Invalid Token — 403
{
"error": "Invalid token",
"code": "auth/invalid-token"
}
Project ID Mismatch — 403
Project ID Mismatch — 403
{
"error": "Project ID mismatch",
"code": "auth/project-mismatch"
}
iss claim in the JWT does not match the request project ID.Username Already Taken — 409
Username Already Taken — 409
{
"error": "Username already taken",
"field": "username",
"code": "DUPLICATE_USERNAME"
}

