Introduction
This documentation aims to provide all the information you need to work with our API.
Mail test server: https://backend-staging.subsig.com:8025
Postman collection: https://backend-staging.subsig.com/docs.postman
OpenAPI spec: https://backend-staging.subsig.com/docs.openapi
Test Users (Development Only)
The following test accounts are available for testing purposes:
| Password | Organisation | Role | |
|---|---|---|---|
admin@acme.com |
password |
Acme Corporation | admin |
admin@acme.com |
password |
Acme Corporation | organisation_owner |
member@acme.com |
password |
Acme Corporation | organisation_member |
project@acme.com |
password |
Acme Corporation | project_member (CRM & Analytics only) |
alice@techstart.com |
password |
TechStart Inc | organisation_owner |
Note: admin@acme.com is also a member of TechStart Inc for testing multi-organisation switching.
Authenticating requests
To authenticate requests, include an Authorization header with the value "Bearer 1|abc123...".
All authenticated endpoints are marked with a requires authentication badge in the documentation below.
You can retrieve your token by visiting your dashboard and clicking Generate API token.
Registration
Create a new user account to access the application.
Create Account
Register a new user account. After successful registration, the user will be automatically logged in and redirected to the dashboard. Personal email addresses are NOT allowed. Verification link is sent via email. /verify-email?code=1234&email=john@example.com
Example request:
const url = new URL(
"http://localhost/register"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "John Doe",
"email": "john@example.com",
"password": "SecurePass123!",
"password_confirmation": "SecurePass123!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201, Account created. User logged in and redirected.):
Example response (422, Validation error.):
{
"message": "The email has already been taken.",
"errors": {
"email": [
"The email has already been taken."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Authentication
APIs for user authentication
Create API Token
Generate an API token for authenticated requests. Requires a verified email address.
Example request:
const url = new URL(
"http://localhost/api/sanctum/token"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "john@example.com",
"password": "SecurePass123!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"token": "1|abc123..."
}
Example response (422, Invalid credentials):
{
"message": "The provided credentials are incorrect.",
"errors": {
"email": [
"The provided credentials are incorrect."
]
}
}
Example response (422, Email not verified):
{
"message": "Please verify your email address before logging in.",
"errors": {
"email": [
"Please verify your email address before logging in."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Verify Email
Verify user's email address using the 4-digit code sent via email. Returns an API token on successful verification. Verification link is sent via email. /verify-email?code=1234&email=john@example.com
Example request:
const url = new URL(
"http://localhost/api/email/verify"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "john@example.com",
"code": "1234"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"message": "Email verified successfully.",
"token": "1|abc123..."
}
Example response (200, Already verified):
{
"message": "Email already verified.",
"token": "1|abc123..."
}
Example response (422, Invalid code):
{
"message": "Invalid verification code.",
"errors": {
"code": [
"Invalid verification code."
]
}
}
Example response (422, Expired code):
{
"message": "Verification code has expired. Please request a new one.",
"errors": {
"code": [
"Verification code has expired. Please request a new one."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Resend Verification Code
Send a new 4-digit verification code to the user's email. Code expires in 60 minutes.
Example request:
const url = new URL(
"http://localhost/api/email/resend"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "john@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"message": "Verification code sent."
}
Example response (200, Already verified):
{
"message": "Email already verified."
}
Example response (422, User not found):
{
"message": "No account found with this email.",
"errors": {
"email": [
"No account found with this email."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Current User
requires authentication
Get the authenticated user's details.
Example request:
const url = new URL(
"http://localhost/api/user"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"name": "John Doe",
"email": "john@example.com",
"email_verified_at": "2025-12-04T12:00:00.000000Z",
"created_at": "2025-12-04T10:00:00.000000Z",
}
Example response (401, Unauthenticated):
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Log In
Authenticate with your email and password to start a session. On success, you receive a token for subsequent requests.
Example request:
const url = new URL(
"http://localhost/login"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "john@example.com",
"password": "SecurePass123!",
"remember": true
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Login successful. Session started.):
Example response (422, Invalid credentials.):
{
"message": "These credentials do not match our records.",
"errors": {
"email": [
"These credentials do not match our records."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Log Out
requires authentication
End your current session. You will need to log in again to access protected resources.
Example request:
const url = new URL(
"http://localhost/logout"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200, Logged out successfully.):
Example response (401, Not logged in.):
{
"message": "Unauthenticated."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Password Reset
Recover access to your account if you forgot your password.
Request Password Reset
Send a password reset link to your email. The link expires after 60 minutes. Same response for security even if email not found.
Example request:
const url = new URL(
"http://localhost/forgot-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"email": "john@example.com"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Reset link sent.):
{
"status": "We have emailed your password reset link."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Reset Password
Set a new password using the token from your email. Token is valid for 60 minutes.
Example request:
const url = new URL(
"http://localhost/reset-password"
);
const headers = {
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"token": "a1b2c3d4e5f6g7h8i9j0",
"email": "john@example.com",
"password": "NewSecurePass123!",
"password_confirmation": "NewSecurePass123!"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200, Password reset successful.):
{
"status": "Your password has been reset."
}
Example response (422, Invalid or expired token.):
{
"message": "This password reset token is invalid.",
"errors": {
"email": [
"This password reset token is invalid."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Onboarding
APIs for user onboarding flow
Complete Onboarding
requires authentication
Create an organisation and project in a single step during onboarding. The authenticated user becomes the organisation owner.
Example request:
const url = new URL(
"http://localhost/api/onboarding"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"organisation_name": "Acme Inc",
"product_name": "Acme CRM",
"product_website": "https:\/\/acme.com",
"product_logo": "https:\/\/cdn.brandfetch.io\/acme.com\/fallback\/lettermark\/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": [],
"reddit_keywords": [
"acme",
"acme crm"
],
"reddit_brand_name": "Acme"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"message": "Onboarding completed successfully.",
"data": {
"organisation": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Inc"
},
"project": {
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"product_name": "Acme CRM",
"product_website": "https://acme.com",
"product_logo": "https://cdn.brandfetch.io/acme.com/fallback/lettermark/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": {},
"reddit_keywords": [
"acme",
"acme crm"
],
"reddit_brand_name": "Acme"
}
}
}
Example response (422, Validation error):
{
"message": "The organisation name field is required.",
"errors": {
"organisation_name": [
"The organisation name field is required."
]
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Organisations
APIs for managing organisations
List Organisations
requires authentication
Get all organisations the authenticated user belongs to.
Example request:
const url = new URL(
"http://localhost/api/organisations"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Inc",
"role": "organisation_owner",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Organisation
requires authentication
Create a new organisation. The authenticated user becomes the admin.
Example request:
const url = new URL(
"http://localhost/api/organisations"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Acme Inc"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"message": "Organisation created successfully.",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Inc",
"role": "organisation_owner",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Organisation
requires authentication
Get details of a specific organisation.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Inc",
"role": "organisation_owner",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Example response (403, No access):
{
"message": "You do not have access to this organisation."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Organisation
requires authentication
Update an organisation's details. Requires admin role.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"name": "Acme Corp"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"message": "Organisation updated successfully.",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Corp",
"role": "organisation_owner",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Example response (403, Not admin):
{
"message": "You must be an organisation admin to perform this action."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Switch Current Organisation
requires authentication
Set the user's current organisation for subsequent requests.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/switch"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "POST",
headers,
}).then(response => response.json());Example response (200):
{
"message": "Switched to organisation successfully.",
"data": {
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"name": "Acme Inc"
}
}
Example response (403, No access):
{
"message": "You do not have access to this organisation."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Projects
APIs for managing projects within organisations
List Projects
requires authentication
Get all projects in an organisation that the user has access to.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/projects"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": [
{
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"product_name": "Acme App",
"product_website": "https://acme.com",
"review_platforms": {
"g2": {
"enabled": true,
"url": "https://g2.com/products/acme"
}
},
"reddit_keywords": [
"acme",
"acme app"
],
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
]
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Create Project
requires authentication
Create a new project in an organisation. Requires organisation admin role.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/projects"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"product_name": "Acme App",
"product_website": "https:\/\/acme.com",
"product_logo": "https:\/\/cdn.brandfetch.io\/acme.com\/fallback\/lettermark\/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": [],
"reddit_keywords": [
"acme",
"acme app"
],
"reddit_brand_name": "Acme"
};
fetch(url, {
method: "POST",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (201):
{
"message": "Project created successfully.",
"data": {
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"product_name": "Acme App",
"product_website": "https://acme.com",
"product_logo": "https://cdn.brandfetch.io/acme.com/fallback/lettermark/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": {},
"reddit_keywords": [
"acme"
],
"reddit_brand_name": "Acme",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Get Project
requires authentication
Get details of a specific project.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/projects/1f12183c-cad2-43e2-b7b7-4a5d7ef2e34a"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "GET",
headers,
}).then(response => response.json());Example response (200):
{
"data": {
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"product_name": "Acme App",
"product_website": "https://acme.com",
"review_platforms": {
"g2": {
"enabled": true,
"url": "https://g2.com/products/acme"
}
},
"reddit_keywords": [
"acme",
"acme app"
],
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Update Project
requires authentication
Update a project's details. Requires organisation admin role.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/projects/1f12183c-cad2-43e2-b7b7-4a5d7ef2e34a"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
let body = {
"product_name": "Acme App Pro",
"product_website": "https:\/\/acme.com",
"product_logo": "https:\/\/cdn.brandfetch.io\/acme.com\/fallback\/lettermark\/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": [],
"reddit_keywords": [
"acme",
"acme pro"
],
"reddit_brand_name": "Acme"
};
fetch(url, {
method: "PUT",
headers,
body: JSON.stringify(body),
}).then(response => response.json());Example response (200):
{
"message": "Project updated successfully.",
"data": {
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"product_name": "Acme App Pro",
"product_website": "https://acme.com",
"product_logo": "https://cdn.brandfetch.io/acme.com/fallback/lettermark/icon?c=BRANDFETCH_CLIENT_ID",
"review_platforms": {},
"reddit_keywords": [
"acme",
"acme pro"
],
"reddit_brand_name": "Acme",
"created_at": "2025-12-10T10:00:00.000000Z",
"updated_at": "2025-12-10T10:00:00.000000Z"
}
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.
Delete Project
requires authentication
Delete a project. Requires organisation admin role.
Example request:
const url = new URL(
"http://localhost/api/organisations/53efd125-269f-4e97-8b25-16a5dc0ccb71/projects/1f12183c-cad2-43e2-b7b7-4a5d7ef2e34a"
);
const headers = {
"Authorization": "Bearer 1|abc123...",
"Content-Type": "application/json",
"Accept": "application/json",
};
fetch(url, {
method: "DELETE",
headers,
}).then(response => response.json());Example response (200):
{
"message": "Project deleted successfully."
}
Received response:
Request failed with error:
Tip: Check that you're properly connected to the network.
If you're a maintainer of ths API, verify that your API is running and you've enabled CORS.
You can check the Dev Tools console for debugging information.