Overview

The SalesGOAT API provides comprehensive endpoints for managing teams, users, projects, paystubs, and related data within a multi-tenant architecture. All operations are scoped to the authenticated user’s tenant, ensuring complete data isolation and security.

Note: All endpoints require authentication with a valid Firebase ID token. Tokens expire after 1 hour (3600 seconds) and must be refreshed using the token generation endpoint.

Field Validation & Data Types

All API endpoints enforce strict field validation:

  • Field Naming: All fields must use snake_case convention (e.g., user_id, created_at)
  • Date Fields: Input as YYYY-MM-DD strings, stored as Firestore Timestamps
  • ID Fields: Optional custom IDs or auto-generated sequential 6-digit zero-padded IDs
  • Required Fields: Must be present and non-empty
  • Field Types: Strictly validated (string, number, boolean, array)
  • Enum Values: Validated against predefined options
  • Unknown Fields: Rejected with 400 error to prevent data corruption
Important: Any fields not explicitly defined in the endpoint documentation will cause the request to fail with a 400 Bad Request error. This prevents accidental data corruption from sending data to the wrong endpoint.

Enhanced Date Handling

The API provides flexible date input support while maintaining data consistency. All date fields are automatically converted to Firestore Timestamps for optimal database storage and querying.

Supported Date Formats

Format Example Description
YYYY-MM-DD "2024-12-31" Simple date format (most common)
ISO String "2024-12-31T14:30:00.000Z" Full ISO 8601 with time
Firestore Timestamp {"_seconds": 1735689600, "_nanoseconds": 0} Firestore Timestamp object
Unix Timestamp 1735689600 Unix timestamp in seconds
Unix Timestamp (ms) 1735689600000 Unix timestamp in milliseconds

Date Field Examples

// All of these are valid for date fields:
{
“closed_date”: “2024-12-31”, // Simple format
“date_paid”: “2024-12-31T14:30:00.000Z”, // ISO string
“install_date”: {“_seconds”: 1735689600, “_nanoseconds”: 0}, // Firestore Timestamp
“m2_date”: 1735689600 // Unix timestamp
}
Automatic Conversion: All date formats are automatically converted to Firestore Timestamps for consistent storage and optimal querying performance.

Authentication

The API uses a secure token system with clear separation of concerns.

Token Types

  • API User Tokens: Long-lived tokens for API access (no expiration)
  • Session Tokens: Short-lived tokens for general API access (1 hour expiration)

Token System

Security: API user tokens can only generate session tokens, while session tokens are used for all other API operations.

Generate API User Token

POST Generate API User Token

/api/v1/auth/api-token

Generate a long-lived API user token for API access. This token can only be used to generate session tokens.

Request Body

Field Type Required Description
email string Yes API user email address
password string Yes* API user password (required if googleIdToken not provided)
tenantId string Yes Tenant ID
googleIdToken string Yes* Google OAuth ID token (required if password not provided)
Note: Provide either password OR googleIdToken, not both.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “API user token generated successfully”,
“data”: {
“customToken”: “eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…”,
“userId”: “user-id”,
“tenantId”: “tenant-id”,
“expiresIn”: null,
“tokenType”: “api_user”
},
“timestamp”: “2025-10-14T22:17:27.454Z”
}

Example Request

curl -X POST https://api.salesgoat.app/api/api/v1/auth/api-token \
-H “Content-Type: application/json” \
-d ‘{
“email”: “admin@example.com”,
“password”: “your-password”,
“tenantId”: “your-tenant-id”
}’

Generate Session Token

POST Generate Session Token

/api/v1/auth/session-token

Generate a short-lived session token using an API user token. This token can be used for all API operations.

Headers

Authorization: Bearer YOUR_API_USER_TOKEN
Content-Type: application/json

Request Body

{}
Note: Empty JSON body is required.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Session token generated successfully”,
“data”: {
“customToken”: “eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…”,
“userId”: “user-id”,
“tenantId”: “tenant-id”,
“expiresIn”: 3600,
“tokenType”: “session”
},
“timestamp”: “2025-10-14T22:17:27.454Z”
}

Example Request

curl -X POST https://api.salesgoat.app/api/api/v1/auth/session-token \
-H “Authorization: Bearer YOUR_API_USER_TOKEN” \
-H “Content-Type: application/json” \
-d ‘{}’

Refresh Token

POST Refresh Token

/api/v1/auth/refresh

Refresh an existing token to get a new session token.

Headers

Authorization: Bearer YOUR_EXISTING_TOKEN
Content-Type: application/json

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Token refreshed successfully”,
“data”: {
“customToken”: “eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9…”,
“userId”: “user-id”,
“tenantId”: “tenant-id”,
“expiresIn”: 3600
},
“timestamp”: “2025-10-14T22:17:27.454Z”
}

Revoke Token

POST Revoke Token

/api/v1/auth/revoke

Revoke a token to invalidate it immediately.

Headers

Authorization: Bearer TOKEN_TO_REVOKE
Content-Type: application/json

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Token has been revoked”,
“data”: {
“message”: “Token revoked successfully”
},
“timestamp”: “2025-10-14T22:17:27.454Z”
}

Using Tokens

Include the appropriate token in the Authorization header for all requests:

Authorization: Bearer YOUR_TOKEN

Token Restrictions

  • API User Tokens: Can ONLY be used with /api/v1/auth/session-token endpoint
  • Session Tokens: Required for all other API operations
  • Expiration: Session tokens expire after 1 hour and must be refreshed

Error Responses

// API User Token used on wrong endpoint
{
“error”: “Forbidden: API user tokens can only be used with /api/v1/auth/session-token endpoint”
}

// Expired token
{
“error”: “Unauthorized: Token has expired”
}

// Invalid token
{
“error”: “Unauthorized: Invalid token”
}

Health Check

GET
Health Check

/api/v1/health

Check the health status of the API service.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Success”,
“data”: {
“status”: “healthy”,
“environment”: “production”,
“projectId”: “reps-e6cf4”,
“timestamp”: “2025-10-10T19:24:56.419Z”
},
“timestamp”: “2025-10-10T19:24:56.419Z”
}

Teams API

GET
List Teams

/api/v1/tenants/{tenantId}/teams

Retrieve a list of all teams for the specified tenant.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of teams to return (default: 50)
offset integer No Number of teams to skip (default: 0)
is_active boolean No Filter by active status

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Teams retrieved successfully”,
“data”: [
{
“id”: “D4u5UDhoRLhoTxAO6O1u”,
“name”: “Sales Team Alpha”,
“is_active”: true,
“team_type”: “Office”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“parent_id”: null,
“created_by”: “s4qmQCYqXrVNsQUMgOvr7yuXkQq1”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Team

/api/v1/tenants/{tenantId}/teams/{teamId}

Retrieve a specific team by its ID.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
teamId string Yes The unique identifier of the team

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Team retrieved successfully”,
“data”: {
“id”: “D4u5UDhoRLhoTxAO6O1u”,
“name”: “Sales Team Alpha”,
“is_active”: true,
“team_type”: “Office”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“parent_id”: null,
“created_by”: “s4qmQCYqXrVNsQUMgOvr7yuXkQq1”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Team

/api/v1/tenants/{tenantId}/teams

Create a new team for the specified tenant.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant

Request Body

Field Type Required Description
name string Yes The name of the team (non-empty string)
is_active boolean Yes Whether the team is active
team_type string Yes Type of team: “Office”, “Region”, or “Division”
tenant_id string Yes The tenant ID (must match URL parameter)
parent_id string No ID of the parent team (optional)

Request Example

{
“name”: “Sales Team Alpha”,
“is_active”: true,
“team_type”: “Office”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“parent_id”: “parent-team-id”
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Team created successfully”,
“data”: {
“id”: “D4u5UDhoRLhoTxAO6O1u”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}
Validation Error Response:
400 Bad Request

{
“success”: false,
“error”: “team_type must be one of: Office, Region, Division”,
“statusCode”: 400,
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Team

/api/v1/tenants/{tenantId}/teams/{teamId}

Update an existing team.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
teamId string Yes The unique identifier of the team

Request Body

Field Type Required Description
name string No The name of the team (non-empty string)
is_active boolean No Whether the team is active
team_type string No Type of team: “Office”, “Region”, or “Division”
tenant_id string No The tenant ID (must match URL parameter)
parent_id string No ID of the parent team (optional)

Request Example

{
“name”: “Updated Team Name”,
“is_active”: false,
“team_type”: “Region”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“parent_id”: “parent-team-id”
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Team updated successfully”,
“data”: {
“id”: “D4u5UDhoRLhoTxAO6O1u”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Team

/api/v1/tenants/{tenantId}/teams/{teamId}

Delete a team permanently.

Warning: This action cannot be undone. All data associated with the team will be permanently deleted.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
teamId string Yes The unique identifier of the team

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Team deleted successfully”,
“data”: {
“id”: “D4u5UDhoRLhoTxAO6O1u”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Users API

GET
List Users

/api/v1/tenants/{tenantId}/users

Retrieve a list of all users for the specified tenant.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of users to return (default: 50)
offset integer No Number of users to skip (default: 0)
role string No Filter by user role
is_active boolean No Filter by active status

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Users retrieved successfully”,
“data”: [
{
“id”: “user-id-123”,
“email”: “user@example.com”,
“first_name”: “John”,
“last_name”: “Doe”,
“roles”: [“admin”],
“is_active”: true,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get User

/api/v1/tenants/{tenantId}/users/{userId}

Retrieve a specific user by their ID.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
userId string Yes The unique identifier of the user

Response

Success Response:
200 OK

{
“success”: true,
“message”: “User retrieved successfully”,
“data”: {
“id”: “user-id-123”,
“email”: “user@example.com”,
“first_name”: “John”,
“last_name”: “Doe”,
“roles”: [“admin”],
“is_active”: true,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create User

/api/v1/tenants/{tenantId}/users

Create a new user for the specified tenant.

Request Body

Field Type Required Description
email string Yes User’s email address
first_name string Yes User’s first name
last_name string Yes User’s last name
roles array Yes Array of user roles
is_active boolean No Whether the user is active (default: true)

Request Example

{
“email”: “newuser@example.com”,
“first_name”: “Jane”,
“last_name”: “Smith”,
“roles”: [“user”],
“is_active”: true
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “User created successfully”,
“data”: {
“id”: “new-user-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update User

/api/v1/tenants/{tenantId}/users/{userId}

Update an existing user.

Request Body

Field Type Required Description
email string No User’s email address
first_name string No User’s first name
last_name string No User’s last name
roles array No Array of user roles
is_active boolean No Whether the user is active

Response

Success Response:
200 OK

{
“success”: true,
“message”: “User updated successfully”,
“data”: {
“id”: “user-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete User

/api/v1/tenants/{tenantId}/users/{userId}

Delete a user permanently.

Warning: This action cannot be undone. All data associated with the user will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “User deleted successfully”,
“data”: {
“id”: “user-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Projects API

GET
List Projects

/api/v1/tenants/{tenantId}/projects

Retrieve a list of all projects for the specified tenant.

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of projects to return (default: 50)
offset integer No Number of projects to skip (default: 0)
status string No Filter by project status
teamId string No Filter by team ID

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Projects retrieved successfully”,
“data”: [
{
“id”: “project-id-123”,
“name”: “Project Alpha”,
“description”: “A sample project”,
“status”: “active”,
“team_id”: “team-id-123”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Project

/api/v1/tenants/{tenantId}/projects/{projectId}

Retrieve a specific project by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project retrieved successfully”,
“data”: {
“id”: “project-id-123”,
“name”: “Project Alpha”,
“description”: “A sample project”,
“status”: “active”,
“team_id”: “team-id-123”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Project

/api/v1/tenants/{tenantId}/projects

Create a new project for the specified tenant.

Request Body

Field Type Required Description
tenant_id string Yes Tenant ID (must match URL parameter)
address string Yes Project address
closed_date string Yes Project close date (YYYY-MM-DD format, converted to Firestore Timestamp)
closer string Yes Closer name
customer_name string Yes Customer name
email string Yes Customer email
lead_token string Yes Lead token
phone string Yes Customer phone number
project_status string Yes Project status
project_type string Yes Project type
self_gen string Yes Self-generated flag
state string Yes State (2-character format)
rep_ids array Yes Array of representative IDs
date_paid string No Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
install_date string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
m2_date string No M2 date (YYYY-MM-DD format, converted to Firestore Timestamp)
installation_details array No Installation details array
manager_ids array No Array of manager IDs

Request Example

{
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“address”: “123 Main St, Anytown, ST 12345”,
“closed_date”: “2025-07-07”,
“closer”: “John Smith”,
“customer_name”: “Martha Johnson”,
“email”: “martha@example.com”,
“lead_token”: “ABC123”,
“phone”: “+12345678909”,
“project_status”: “M3 Paid”,
“project_type”: “Solar Only”,
“self_gen”: “No”,
“state”: “CA”,
“rep_ids”: [“40”, “2494”],
“date_paid”: “2025-10-01”,
“install_date”: “2025-09-15”,
“m2_date”: “2025-10-01”,
“installation_details”: [“Detail 1”, “Detail 2”],
“manager_ids”: [“manager1”, “manager2”]
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Project created successfully”,
“data”: {
“id”: “new-project-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Project

/api/v1/tenants/{tenantId}/projects/{projectId}

Update an existing project.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project updated successfully”,
“data”: {
“id”: “project-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Project

/api/v1/tenants/{tenantId}/projects/{projectId}

Delete a project permanently.

Warning: This action cannot be undone. All data associated with the project will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project deleted successfully”,
“data”: {
“id”: “project-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Project Overviews API

GET
List Project Overviews

/api/v1/tenants/{tenantId}/project-overviews

Retrieve a list of all project overviews for the specified tenant.

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of overviews to return (default: 50)
offset integer No Number of overviews to skip (default: 0)
salesProfessionalId string No Filter by sales professional ID

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project overviews retrieved successfully”,
“data”: [
{
“id”: “overview-id-123”,
“project_id”: “project-id-123”,
“sales_professional_id”: “user-id-123”,
“total_sales”: 50000.00,
“commission”: 5000.00,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Project Overview

/api/v1/tenants/{tenantId}/project-overviews/{overviewId}

Retrieve a specific project overview by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project overview retrieved successfully”,
“data”: {
“id”: “overview-id-123”,
“project_id”: “project-id-123”,
“sales_professional_id”: “user-id-123”,
“total_sales”: 50000.00,
“commission”: 5000.00,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Project Overview

/api/v1/tenants/{tenantId}/project-overviews

Create a new project overview for the specified tenant.

Request Body

Field Type Required Description
project_id string Yes Associated project ID
sales_professional_id string Yes Sales professional user ID
total_sales number No Total sales amount
commission number No Commission amount

Request Example

{
“project_id”: “project-id-123”,
“sales_professional_id”: “user-id-123”,
“total_sales”: 50000.00,
“commission”: 5000.00
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Project overview created successfully”,
“data”: {
“id”: “new-overview-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Project Overview

/api/v1/tenants/{tenantId}/project-overviews/{overviewId}

Update an existing project overview.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project overview updated successfully”,
“data”: {
“id”: “overview-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Project Overview

/api/v1/tenants/{tenantId}/project-overviews/{overviewId}

Delete a project overview permanently.

Warning: This action cannot be undone. All data associated with the project overview will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Project overview deleted successfully”,
“data”: {
“id”: “overview-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Paystubs API

GET
List Paystubs

/api/v1/tenants/{tenantId}/paystubs

Retrieve a list of all paystubs for the specified tenant.

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of paystubs to return (default: 50)
offset integer No Number of paystubs to skip (default: 0)
salesProfessionalId string No Filter by sales professional ID
startDate string No Filter by start date (ISO format)
endDate string No Filter by end date (ISO format)

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystubs retrieved successfully”,
“data”: [
{
“id”: “paystub-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“sales_professional_id”: “40”,
“total_this_period”: 6777.00,
“scpfs”: {
“1”: {
“customer_name”: “George Harper”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77133”,
“sales_professional_id”: “40”,
“total_this_period”: 830.00
},
“2”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77132”,
“sales_professional_id”: “40”,
“total_this_period”: 820.00
},
“3”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “M2 & M3”,
“related_scpf_id”: “77125”,
“sales_professional_id”: “40”,
“total_this_period”: 5127.00
}
},
“period_start_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“period_end_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“gross_pay”: 5000.00,
“net_pay”: 4000.00,
“deductions”: 1000.00,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Paystub

/api/v1/tenants/{tenantId}/paystubs/{paystubId}

Retrieve a specific paystub by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub retrieved successfully”,
“data”: {
“id”: “paystub-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“sales_professional_id”: “40”,
“total_this_period”: 6777.00,
“scpfs”: {
“1”: {
“customer_name”: “George Harper”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77133”,
“sales_professional_id”: “40”,
“total_this_period”: 830.00
},
“2”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77132”,
“sales_professional_id”: “40”,
“total_this_period”: 820.00
},
“3”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “M2 & M3”,
“related_scpf_id”: “77125”,
“sales_professional_id”: “40”,
“total_this_period”: 5127.00
}
},
“period_start_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“period_end_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“gross_pay”: 5000.00,
“net_pay”: 4000.00,
“deductions”: 1000.00,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Paystub

/api/v1/tenants/{tenantId}/paystubs

Create a new paystub for the specified tenant.

Request Body

Field Type Required Description
tenant_id string Yes Tenant ID (must match URL parameter)
pay_date string Yes Pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
sales_professional_id string Yes Sales professional user ID
total_this_period number Yes Total amount for this period (stored as cents, e.g., 677700 for $6,777.00)
scpfs object Yes Nested object containing SCPF entries (at least one required)
period_start_date string No Pay period start date (YYYY-MM-DD format, converted to Firestore Timestamp)
period_end_date string No Pay period end date (YYYY-MM-DD format, converted to Firestore Timestamp)
gross_pay number No Gross pay amount (stored as dollar amount)
net_pay number No Net pay amount (stored as dollar amount)
deductions number No Total deductions (stored as dollar amount)

SCPFs Object Structure

The scpfs field is a nested object where each key represents an SCPF entry. Each SCPF entry must contain the following required fields:

Field Type Required Description
customer_name string Yes Customer name for this SCPF entry
pay_type string Yes Type of payment (e.g., “Closer Override”, “M2 & M3”)
related_scpf_id string Yes Related SCPF ID
sales_professional_id string Yes Sales professional user ID
total_this_period number Yes Total amount for this SCPF entry (stored as dollar amount)

Request Example

{
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: “2025-10-15”,
“sales_professional_id”: “40”,
“total_this_period”: 6777.00,
“scpfs”: {
“1”: {
“customer_name”: “George Harper”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77133”,
“sales_professional_id”: “40”,
“total_this_period”: 830.00
},
“2”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “Closer Override”,
“related_scpf_id”: “77132”,
“sales_professional_id”: “40”,
“total_this_period”: 820.00
},
“3”: {
“customer_name”: “Kenneth Bowman”,
“pay_type”: “M2 & M3”,
“related_scpf_id”: “77125”,
“sales_professional_id”: “40”,
“total_this_period”: 5127.00
}
},
“period_start_date”: “2025-10-01”,
“period_end_date”: “2025-10-15”,
“gross_pay”: 5000.00,
“net_pay”: 4000.00,
“deductions”: 100000
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Paystub created successfully”,
“data”: {
“id”: “new-paystub-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Paystub

/api/v1/tenants/{tenantId}/paystubs/{paystubId}

Update an existing paystub.

Request Body

Field Type Required Description
tenant_id string No Tenant ID (must match URL parameter if provided)
pay_date string No Pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
sales_professional_id string No Sales professional user ID
total_this_period number No Total amount for this period (stored as cents, e.g., 677700 for $6,777.00)
scpfs object No Nested object containing SCPF entries (at least one required if provided)
period_start_date string No Pay period start date (YYYY-MM-DD format, converted to Firestore Timestamp)
period_end_date string No Pay period end date (YYYY-MM-DD format, converted to Firestore Timestamp)
gross_pay number No Gross pay amount (stored as dollar amount)
net_pay number No Net pay amount (stored as dollar amount)
deductions number No Total deductions (stored as dollar amount)

Request Example

{
“pay_date”: “2025-10-20”,
“total_this_period”: 750000,
“scpfs”: {
“1”: {
“customer_name”: “Updated Customer”,
“pay_type”: “Updated Payment”,
“related_scpf_id”: “77134”,
“sales_professional_id”: “40”,
“total_this_period”: 90000
}
}
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub updated successfully”,
“data”: {
“id”: “paystub-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Paystub

/api/v1/tenants/{tenantId}/paystubs/{paystubId}

Delete a paystub permanently.

Warning: This action cannot be undone. All data associated with the paystub will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub deleted successfully”,
“data”: {
“id”: “paystub-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Paystub Overviews API

GET
List Paystub Overviews

/api/v1/tenants/{tenantId}/paystub-overview

Retrieve a list of all paystub overviews for the specified tenant.

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of overviews to return (default: 50)
offset integer No Number of overviews to skip (default: 0)
salesProfessionalId string No Filter by sales professional ID

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub overviews retrieved successfully”,
“data”: [
{
“id”: “overview-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“sales_professional_id”: “user-id-123”,
“total_this_period”: 1500.00,
“assist_pay_pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“build_partner”: “SolarCorp”,
“customer_name”: “John Smith”,
“lead_token”: “ABC123”,
“project_status”: “M3 Paid”,
“project_type”: “Solar Only”,
“self_gen”: “No”,
“rep_ids”: [“40”, “2494”],
“manager_ids”: [“manager1”, “manager2”],
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Paystub Overview

/api/v1/tenants/{tenantId}/paystub-overview/{overviewId}

Retrieve a specific paystub overview by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub overview retrieved successfully”,
“data”: {
“id”: “overview-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“sales_professional_id”: “user-id-123”,
“total_this_period”: 1500.00,
“assist_pay_pay_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“build_partner”: “SolarCorp”,
“customer_name”: “John Smith”,
“lead_token”: “ABC123”,
“project_status”: “M3 Paid”,
“project_type”: “Solar Only”,
“self_gen”: “No”,
“rep_ids”: [“40”, “2494”],
“manager_ids”: [“manager1”, “manager2”],
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Paystub Overview

/api/v1/tenants/{tenantId}/paystub-overview

Create a new paystub overview for the specified tenant.

Request Body

Field Type Required Description
tenant_id string Yes Tenant ID (must match URL parameter)
pay_date string Yes Pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
sales_professional_id string Yes Sales professional user ID
total_this_period number Yes Total amount for this period (stored as dollar amount, e.g., 1500.00 for $1,500.00)
assist_pay_pay_date string No Assist pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
assist_pay_period_start_date string No Assist pay period start date (YYYY-MM-DD format, converted to Firestore Timestamp)
date_paid string No Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
install_date string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
m2_date string No M2 date (YYYY-MM-DD format, converted to Firestore Timestamp)
build_partner string No Build partner name
customer_name string No Customer name
lead_token string No Lead token
project_status string No Project status
project_type string No Project type
self_gen string No Self-generated flag
rep_ids array No Array of representative IDs
manager_ids array No Array of manager IDs

Request Example

{
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“pay_date”: “2025-01-15”,
“sales_professional_id”: “user-id-123”,
“total_this_period”: 1500.00,
“assist_pay_pay_date”: “2025-01-10”,
“assist_pay_period_start_date”: “2025-01-01”,
“date_paid”: “2025-01-15”,
“install_date”: “2025-01-05”,
“m2_date”: “2025-01-20”,
“build_partner”: “SolarCorp”,
“customer_name”: “John Smith”,
“lead_token”: “ABC123”,
“project_status”: “M3 Paid”,
“project_type”: “Solar Only”,
“self_gen”: “No”,
“rep_ids”: [“40”, “2494”],
“manager_ids”: [“manager1”, “manager2”]
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Paystub overview created successfully”,
“data”: {
“id”: “new-overview-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Paystub Overview

/api/v1/tenants/{tenantId}/paystub-overview/{overviewId}

Update an existing paystub overview.

Request Body

Field Type Required Description
tenant_id string No Tenant ID (must match URL parameter if provided)
pay_date string No Pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
sales_professional_id string No Sales professional user ID
total_this_period number No Total amount for this period (stored as dollar amount, e.g., 1500.00 for $1,500.00)
assist_pay_pay_date string No Assist pay date (YYYY-MM-DD format, converted to Firestore Timestamp)
assist_pay_period_start_date string No Assist pay period start date (YYYY-MM-DD format, converted to Firestore Timestamp)
date_paid string No Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
install_date string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
m2_date string No M2 date (YYYY-MM-DD format, converted to Firestore Timestamp)
build_partner string No Build partner name
customer_name string No Customer name
lead_token string No Lead token
project_status string No Project status
project_type string No Project type
self_gen string No Self-generated flag
rep_ids array No Array of representative IDs
manager_ids array No Array of manager IDs

Request Example

{
“pay_date”: “2025-01-20”,
“total_this_period”: 1750.00,
“project_status”: “M4 Paid”,
“customer_name”: “Jane Doe”
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub overview updated successfully”,
“data”: {
“id”: “overview-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Paystub Overview

/api/v1/tenants/{tenantId}/paystub-overview/{overviewId}

Delete a paystub overview permanently.

Warning: This action cannot be undone. All data associated with the paystub overview will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Paystub overview deleted successfully”,
“data”: {
“id”: “overview-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

SCPFs API

GET
List SCPFs

/api/v1/tenants/{tenantId}/scpfs

Retrieve a list of all SCPFs (Sales Commission Prep Files) for the specified tenant.

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of SCPFs to return (default: 50)
offset integer No Number of SCPFs to skip (default: 0)
salesProfessionalId string No Filter by sales professional ID
status string No Filter by SCPF status

Response

Success Response:
200 OK

{
“success”: true,
“message”: “SCPFs retrieved successfully”,
“data”: [
{
“id”: “scpf-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“closed_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“closer”: “John Smith”,
“closer_id”: “closer-123”,
“customer_name”: “Jane Doe”,
“install”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“lead_name”: “Lead Source ABC”,
“lead_rep_id”: “rep-456”,
“pay_type”: “M2 & M3”,
“paystubId”: “paystub-789”,
“sales_professional_id”: “user-123”,
“scpf_id”: “scpf-001”,
“total_this_period”: 1500.00,
“build_partner”: “SolarCorp”,
“customer_ppw”: 3.25,
“dealer_fee”: 50.00,
“lead_deduction”: 20.00,
“lead_pay”: 80.00,
“lead_pkw”: 3.50,
“manager_override”: 10.00,
“net_commission_ppw”: 2.75,
“notes”: “Special installation requirements”,
“opportunity_id”: “opp-12345”,
“redline”: 15.00,
“paystub_name_alpha”: “Doe_Jane”,
“sentinel_fee”: 3.00,
“sow_adder”: 5.00,
“system_size”: 8.5,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get SCPF

/api/v1/tenants/{tenantId}/scpfs/{scpfId}

Retrieve a specific SCPF by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “SCPF retrieved successfully”,
“data”: {
“id”: “scpf-id-123”,
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“closed_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“closer”: “John Smith”,
“closer_id”: “closer-123”,
“customer_name”: “Jane Doe”,
“install”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“lead_name”: “Lead Source ABC”,
“lead_rep_id”: “rep-456”,
“pay_type”: “M2 & M3”,
“paystubId”: “paystub-789”,
“sales_professional_id”: “user-123”,
“scpf_id”: “scpf-001”,
“total_this_period”: 1500.00,
“build_partner”: “SolarCorp”,
“customer_ppw”: 3.25,
“dealer_fee”: 50.00,
“lead_deduction”: 20.00,
“lead_pay”: 80.00,
“lead_pkw”: 3.50,
“manager_override”: 10.00,
“net_commission_ppw”: 2.75,
“notes”: “Special installation requirements”,
“opportunity_id”: “opp-12345”,
“redline”: 15.00,
“paystub_name_alpha”: “Doe_Jane”,
“sentinel_fee”: 3.00,
“sow_adder”: 5.00,
“system_size”: 8.5,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create SCPF

/api/v1/tenants/{tenantId}/scpfs

Create a new SCPF (Solar Commission Prep File) for the specified tenant.

Request Body

Field Type Required Description
tenant_id string Yes Tenant ID (must match URL parameter)
closed_date string Yes Closed date (YYYY-MM-DD format, converted to Firestore Timestamp)
closer string Yes Closer name
closer_id string Yes Closer ID
customer_name string Yes Customer name
install string Yes Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
lead_name string Yes Lead name
lead_rep_id string Yes Lead representative ID
pay_type string Yes Payment type
paystubId string Yes Associated paystub ID
sales_professional_id string Yes Sales professional user ID
scpf_id string Yes SCPF identifier
total_this_period number Yes Total amount for this period (stored as dollar amount, e.g., 1500.00 for $1,500.00)
build_partner string No Build partner name
customer_ppw number No Customer price per watt
dealer_fee number No Dealer fee amount (stored as dollar amount)
lead_deduction number No Lead deduction amount (stored as dollar amount)
lead_pay number No Lead pay amount (stored as dollar amount)
lead_pkw number No Lead price per kilowatt
manager_override number No Manager override amount (stored as dollar amount)
net_commission_ppw number No Net commission price per watt
notes string No Additional notes
opportunity_id string No Opportunity identifier
redline number No Redline amount (stored as dollar amount)
paystub_name_alpha string No Paystub name in alphabetical format
sentinel_fee number No Sentinel fee amount (stored as dollar amount)
sow_adder number No SOW adder amount (stored as dollar amount)
system_size number No System size in kilowatts

Request Example

{
“tenant_id”: “1A2B3C4D-5E6F7G8H-9I0J1K2L-3M4N5O6P-7Q8R9S0T”,
“closed_date”: “2025-01-15”,
“closer”: “John Smith”,
“closer_id”: “closer-123”,
“customer_name”: “Jane Doe”,
“install”: “2025-01-20”,
“lead_name”: “Lead Source ABC”,
“lead_rep_id”: “rep-456”,
“pay_type”: “M2 & M3”,
“paystubId”: “paystub-789”,
“sales_professional_id”: “user-123”,
“scpf_id”: “scpf-001”,
“total_this_period”: 1500.00,
“build_partner”: “SolarCorp”,
“customer_ppw”: 3.25,
“dealer_fee”: 50.00,
“lead_deduction”: 20.00,
“lead_pay”: 80.00,
“lead_pkw”: 3.50,
“manager_override”: 10.00,
“net_commission_ppw”: 2.75,
“notes”: “Special installation requirements”,
“opportunity_id”: “opp-12345”,
“redline”: 15.00,
“paystub_name_alpha”: “Doe_Jane”,
“sentinel_fee”: 3.00,
“sow_adder”: 5.00,
“system_size”: 8.5
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “SCPF created successfully”,
“data”: {
“id”: “new-scpf-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update SCPF

/api/v1/tenants/{tenantId}/scpfs/{scpfId}

Update an existing SCPF.

Request Body

Field Type Required Description
tenant_id string No Tenant ID (must match URL parameter if provided)
closed_date string No Closed date (YYYY-MM-DD format, converted to Firestore Timestamp)
closer string No Closer name
closer_id string No Closer ID
customer_name string No Customer name
install string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
lead_name string No Lead name
lead_rep_id string No Lead representative ID
pay_type string No Payment type
paystubId string No Associated paystub ID
sales_professional_id string No Sales professional user ID
scpf_id string No SCPF identifier
total_this_period number No Total amount for this period (stored as dollar amount, e.g., 1500.00 for $1,500.00)
build_partner string No Build partner name
customer_ppw number No Customer price per watt
dealer_fee number No Dealer fee amount (stored as dollar amount)
lead_deduction number No Lead deduction amount (stored as dollar amount)
lead_pay number No Lead pay amount (stored as dollar amount)
lead_pkw number No Lead price per kilowatt
manager_override number No Manager override amount (stored as dollar amount)
net_commission_ppw number No Net commission price per watt
notes string No Additional notes
opportunity_id string No Opportunity identifier
redline number No Redline amount (stored as dollar amount)
paystub_name_alpha string No Paystub name in alphabetical format
sentinel_fee number No Sentinel fee amount (stored as dollar amount)
sow_adder number No SOW adder amount (stored as dollar amount)
system_size number No System size in kilowatts

Request Example

{
“customer_name”: “Updated Customer Name”,
“total_this_period”: 1750.00,
“notes”: “Updated installation notes”,
“system_size”: 9.2
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “SCPF updated successfully”,
“data”: {
“id”: “scpf-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete SCPF

/api/v1/tenants/{tenantId}/scpfs/{scpfId}

Delete a SCPF permanently.

Warning: This action cannot be undone. All data associated with the SCPF will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “SCPF deleted successfully”,
“data”: {
“id”: “scpf-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Overrides API

GET
List Overrides

/api/v1/tenants/{tenantId}/users/{managerId}/overrides

Retrieve a list of all overrides for the specified manager.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
managerId string Yes The sales_professional_uid of the manager

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of overrides to return (default: 50)
offset integer No Number of overrides to skip (default: 0)
repId string No Filter by rep’s sales_professional_uid
startDate string No Filter by start date (YYYY-MM-DD format)
endDate string No Filter by end date (YYYY-MM-DD format)

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Overrides retrieved successfully”,
“data”: [
{
“id”: “override-id-123”,
“amount”: 1500.00,
“customer_name”: “John Smith”,
“date_paid”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“manager_id”: “manager-123”,
“rep_id”: “rep-456”,
“rep_name”: “Jane Doe”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Override

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}

Retrieve a specific override by its ID.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
managerId string Yes The sales_professional_uid of the manager
overrideId string Yes The unique identifier of the override

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override retrieved successfully”,
“data”: {
“id”: “override-id-123”,
“amount”: 1500.00,
“customer_name”: “John Smith”,
“date_paid”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“manager_id”: “manager-123”,
“rep_id”: “rep-456”,
“rep_name”: “Jane Doe”,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Override

/api/v1/tenants/{tenantId}/users/{managerId}/overrides

Create a new override for the specified manager.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
managerId string Yes The sales_professional_uid of the manager

Request Body

Field Type Required Description
amount number Yes Override amount (stored as dollar amount, e.g., 1500.00 for $1,500.00)
customer_name string Yes Customer name
date_paid string Yes Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
manager_id string Yes Manager’s sales_professional_uid (must match URL parameter)
rep_id string Yes Rep’s sales_professional_uid
rep_name string Yes Rep’s name

Request Example

{
“amount”: 1500.00,
“customer_name”: “John Smith”,
“date_paid”: “2025-01-15”,
“manager_id”: “manager-123”,
“rep_id”: “rep-456”,
“rep_name”: “Jane Doe”
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Override created successfully”,
“data”: {
“id”: “new-override-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Override

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}

Update an existing override.

Request Body

Field Type Required Description
amount number No Override amount (stored as dollar amount)
customer_name string No Customer name
date_paid string No Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
manager_id string No Manager’s sales_professional_uid (must match URL parameter if provided)
rep_id string No Rep’s sales_professional_uid
rep_name string No Rep’s name

Request Example

{
“amount”: 1750.00,
“customer_name”: “Updated Customer Name”
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override updated successfully”,
“data”: {
“id”: “override-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Override

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}

Delete an override permanently.

Warning: This action cannot be undone. All data associated with the override will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override deleted successfully”,
“data”: {
“id”: “override-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Override Details API

GET
List Override Details

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}/details

Retrieve a list of all override details for the specified override.

Path Parameters

Parameter Type Required Description
tenantId string Yes The unique identifier of the tenant
managerId string Yes The sales_professional_uid of the manager
overrideId string Yes The unique identifier of the override

Query Parameters

Parameter Type Required Description
limit integer No Maximum number of details to return (default: 50)
offset integer No Number of details to skip (default: 0)

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override details retrieved successfully”,
“data”: [
{
“id”: “detail-id-123”,
“closed_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“closer”: “John Smith”,
“customer_name”: “Jane Doe”,
“date_paid”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“total_this_period”: 2500.00,
“build_partner”: “SolarCorp”,
“install_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“lead_rep”: “Lead Rep Name”,
“manager_override”: 500.00,
“system_size”: 8.5,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
}
],
“timestamp”: “2025-10-10T18:52:56.419Z”
}

GET
Get Override Detail

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}/details/{detailId}

Retrieve a specific override detail by its ID.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override detail retrieved successfully”,
“data”: {
“id”: “detail-id-123”,
“closed_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“closer”: “John Smith”,
“customer_name”: “Jane Doe”,
“date_paid”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“total_this_period”: 2500.00,
“build_partner”: “SolarCorp”,
“install_date”: {
“_seconds”: 1735689600,
“_nanoseconds”: 0
},
“lead_rep”: “Lead Rep Name”,
“manager_override”: 500.00,
“system_size”: 8.5,
“created_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
},
“updated_at”: {
“_seconds”: 1760122266,
“_nanoseconds”: 975000000
}
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

POST
Create Override Detail

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}/details

Create a new override detail for the specified override.

Request Body

Field Type Required Description
closed_date string Yes Closed date (YYYY-MM-DD format, converted to Firestore Timestamp)
closer string Yes Closer name
customer_name string Yes Customer name
date_paid string Yes Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
total_this_period number Yes Total amount for this period (stored as dollar amount)
build_partner string No Build partner name
install_date string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
lead_rep string No Lead representative name
manager_override number No Manager override amount (stored as dollar amount)
system_size number No System size in kilowatts

Request Example

{
“closed_date”: “2025-01-15”,
“closer”: “John Smith”,
“customer_name”: “Jane Doe”,
“date_paid”: “2025-01-20”,
“total_this_period”: 2500.00,
“build_partner”: “SolarCorp”,
“install_date”: “2025-01-18”,
“lead_rep”: “Lead Rep Name”,
“manager_override”: 500.00,
“system_size”: 8.5
}

Response

Success Response:
201 Created

{
“success”: true,
“message”: “Override detail created successfully”,
“data”: {
“id”: “new-detail-id”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

PUT
Update Override Detail

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}/details/{detailId}

Update an existing override detail.

Request Body

Field Type Required Description
closed_date string No Closed date (YYYY-MM-DD format, converted to Firestore Timestamp)
closer string No Closer name
customer_name string No Customer name
date_paid string No Date paid (YYYY-MM-DD format, converted to Firestore Timestamp)
total_this_period number No Total amount for this period (stored as dollar amount)
build_partner string No Build partner name
install_date string No Installation date (YYYY-MM-DD format, converted to Firestore Timestamp)
lead_rep string No Lead representative name
manager_override number No Manager override amount (stored as dollar amount)
system_size number No System size in kilowatts

Request Example

{
“total_this_period”: 2750.00,
“manager_override”: 600.00,
“system_size”: 9.2
}

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override detail updated successfully”,
“data”: {
“id”: “detail-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

DELETE
Delete Override Detail

/api/v1/tenants/{tenantId}/users/{managerId}/overrides/{overrideId}/details/{detailId}

Delete an override detail permanently.

Warning: This action cannot be undone. All data associated with the override detail will be permanently deleted.

Response

Success Response:
200 OK

{
“success”: true,
“message”: “Override detail deleted successfully”,
“data”: {
“id”: “detail-id-123”
},
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Error Responses

401 Unauthorized

{
“success”: false,
“error”: “Unauthorized: Invalid token”,
“statusCode”: 401,
“timestamp”: “2025-10-10T18:52:56.419Z”
}
403 Forbidden

{
“success”: false,
“error”: “Forbidden: No access to this tenant”,
“statusCode”: 403,
“timestamp”: “2025-10-10T18:52:56.419Z”
}
404 Not Found

{
“success”: false,
“error”: “Resource not found”,
“statusCode”: 404,
“timestamp”: “2025-10-10T18:52:56.419Z”
}
500 Internal Server Error

{
“success”: false,
“error”: “Internal server error”,
“statusCode”: 500,
“timestamp”: “2025-10-10T18:52:56.419Z”
}

Status Codes

Code Description
200 Success (GET, PUT, DELETE)
201 Created (POST)
400 Bad Request
401 Unauthorized (invalid/missing token)
403 Forbidden (no access to tenant)
404 Not Found
500 Internal Server Error

Rate Limiting

API requests are subject to rate limiting. If you exceed the rate limit, you will receive a 429 Too Many Requests response.

Support

For technical support or questions about the API, please contact your system administrator.

Last Updated: October 14, 2025
API Version: v1
Documentation Version: 1.0
Total Endpoints: 39