Reworked API Documentation

Welcome to the official Reworked.ai API documentation. Our REST API lets you add opportunity scoring and generate AI-qualified opportunities directly to your existing systems and workflows, so you can focus on high-quality prospects and stop spending money on low-quality ones.


This document is the complete technical reference for both of Reworked.ai’s API suites:

  • Lead Scoring API. Submit your existing prospect files for AI-powered scoring and enrichment, so you can prioritize the best ones.

  • Opportunities API. Generate and purchase new opportunities by zip code, city, county, or a radius around an address, with optional add-ons for enrichment and mail or digital ad campaigns.


BASE URL

Contact your point of contact at Reworked.ai to obtain the base URL

CLIENT LIBRARIES

Generate JWT Tokens

Authentication with the Reworked.ai API is handled through JSON Web Tokens (JWT). This secure authentication method ensures that only authorized applications can access your lead data and our scoring services.


To authenticate with our API:

Generate an API key in your Reworked.ai dashboard

Exchange your API key for a JWT token using the authentication endpoint

Include this token in the authorization header of subsequent requests


The JWT token will be valid for 48 hours, after which you'll need to generate a new one.

ENDPOINT

/generate-token

METHOD

POST

Request Body

When sending leads for scoring, your request body should include all relevant lead information. The more data you provide, the more accurate our scoring will be.

api_key

will be provided by Reworked.

email

email id you used to create an account on Reworked.ai.

REQUEST BODY

{

"api_key": "api-key",

"email": "abc@gmail.com"

}

Response

The Reworked.ai API returns a structured response.

Status Code

200

The token should be sent as an authorization header in the

process-leads

API

RESPONSE

{

"msg": "Token generated successfully",

"data": {

"token": "Auth Token",

"expiresAt": "Timestamp"

}

}

Error Cases

Our API includes comprehensive error handling to help you quickly diagnose and resolve issues during integration.

Status Code

404

CASE 1

{

"msg": "Api key is invalid",

"data": null

}

CASE 2

{

"msg": "Customer data not found",

"data": null

}

Lead Scoring API

Lead Scoring API

Lead Scoring API

The Lead Scoring API enables authorized users to submit existing lead data for AI-powered scoring and enrichment. Leads can be submitted through a file URL or inline JSON payload. Reworked.ai processes lead data according to the selected industry profile, applying industry-specific enrichment and scoring logic to help businesses identify, evaluate, and prioritize potential opportunities.

The Lead Scoring API enables authorized users to submit existing lead data for AI-powered scoring and enrichment. Leads can be submitted through a file URL or inline JSON payload. Reworked.ai processes lead data according to the selected industry profile, applying industry-specific enrichment and scoring logic to help businesses identify, evaluate, and prioritize potential opportunities.

The Lead Scoring API enables authorized users to submit existing lead data for AI-powered scoring and enrichment. Leads can be submitted through a file URL or inline JSON payload. Reworked.ai processes lead data according to the selected industry profile, applying industry-specific enrichment and scoring logic to help businesses identify, evaluate, and prioritize potential opportunities.

•

Supports multiple industries, including Roofing and Real Estate Investors. The selected industry profile determines which enrichment and scoring workflows are applied.

Supports multiple industries, including Roofing and Real Estate Investors. The selected industry profile determines which enrichment and scoring workflows are applied.

Supports multiple industries, including Roofing and Real Estate Investors. The selected industry profile determines which enrichment and scoring workflows are applied.

ENDPOINT

Copy

Copy

Copy

POST {{base_url}}/api/process-leads

POST {{base_url}}/api/process-leads

POST {{base_url}}/api/process-leads

AUTHENTICATION

Copy

Copy

Copy

Authorization: Bearer <your-jwt-token>
Content-Type: application/json

Authorization: Bearer <your-jwt-token>
Content-Type: application/json

Authorization: Bearer <your-jwt-token>
Content-Type: application/json

TOKEN EXPIRY

Copy

Copy

Copy

JWT tokens are valid for 24 hours. Generate a new token after expiry.

JWT tokens are valid for 24 hours. Generate a new token after expiry.

JWT tokens are valid for 24 hours. Generate a new token after expiry.

Process Leads

Process Leads

Process Leads

Submit lead records by file URL or inline JSON. If both industry_profile_type and industry_profile_id are provided, industry_profile_type takes precedence. If no profile is specified, processing depends on your account’s default behavior.

Submit lead records by file URL or inline JSON. If both industry_profile_type and industry_profile_id are provided, industry_profile_type takes precedence. If no profile is specified, processing depends on your account’s default behavior.

Submit lead records by file URL or inline JSON. If both industry_profile_type and industry_profile_id are provided, industry_profile_type takes precedence. If no profile is specified, processing depends on your account’s default behavior.

•

Authorization

Authorization

Authorization

Required string. Valid authentication token obtained from /generate-token.

Required string. Valid authentication token obtained from /generate-token.

Required string. Valid authentication token obtained from /generate-token.

•

email

email

email

Required string. Email associated with the user’s Reworked.ai account.

Required string. Email associated with the user’s Reworked.ai account.

Required string. Email associated with the user’s Reworked.ai account.

•

input_type

input_type

input_type

Required string. Supported values: url and json.

Required string. Supported values: url and json.

Required string. Supported values: url and json.

•

file_url

file_url

file_url

Conditional string. Required when input_type is url.

Conditional string. Required when input_type is url.

Conditional string. Required when input_type is url.

•

input_data

input_data

input_data

Conditional object. Required when input_type is json.

Conditional object. Required when input_type is json.

Conditional object. Required when input_type is json.

•

industry_profile_type

industry_profile_type

industry_profile_type

Optional string, e.g. ROOFING or REAL_ESTATE_INVESTORS.

Optional string, e.g. ROOFING or REAL_ESTATE_INVESTORS.

Optional string, e.g. ROOFING or REAL_ESTATE_INVESTORS.

•

industry_profile_id

industry_profile_id

industry_profile_id

Optional string. Identifier of a specific industry profile.

Optional string. Identifier of a specific industry profile.

Optional string. Identifier of a specific industry profile.

•

callback_url

callback_url

callback_url

Optional string. Webhook URL for completion notification.

Optional string. Webhook URL for completion notification.

Optional string. Webhook URL for completion notification.

•

overwrite

overwrite

overwrite

Optional boolean. Whether duplicate records should be overwritten.

Optional boolean. Whether duplicate records should be overwritten.

Optional boolean. Whether duplicate records should be overwritten.

•

customer_request_id

customer_request_id

customer_request_id

Optional string. External tracking identifier supplied by the customer.

Optional string. External tracking identifier supplied by the customer.

Optional string. External tracking identifier supplied by the customer.

FILE-BASED REQUEST

Copy

Copy

Copy

POST {{base_url}}/api/process-leads
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
“email”: “you@company.com”,
“input_type”: “url”,
“file_url”: “https://storage.example.com/leads.csv”,
“callback_url”: “https://your-app.com/webhooks/reworked”,
“overwrite”: true,
“industry_profile_type”: “ROOFING”,
“customer_request_id”: “batch-2026-001”
}

POST {{base_url}}/api/process-leads
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
“email”: “you@company.com”,
“input_type”: “url”,
“file_url”: “https://storage.example.com/leads.csv”,
“callback_url”: “https://your-app.com/webhooks/reworked”,
“overwrite”: true,
“industry_profile_type”: “ROOFING”,
“customer_request_id”: “batch-2026-001”
}

POST {{base_url}}/api/process-leads
Authorization: Bearer <your-jwt-token>
Content-Type: application/json

{
“email”: “you@company.com”,
“input_type”: “url”,
“file_url”: “https://storage.example.com/leads.csv”,
“callback_url”: “https://your-app.com/webhooks/reworked”,
“overwrite”: true,
“industry_profile_type”: “ROOFING”,
“customer_request_id”: “batch-2026-001”
}

INLINE JSON REQUEST

Copy

Copy

Copy

{
“email”: “you@company.com”,
“input_type”: “json”,
“input_data”: {
“replace_with”: “lead data matching the supported JSON schema”
},
“industry_profile_type”: “REAL_ESTATE_INVESTORS”,
“customer_request_id”: “request-2026-001”
}

{
“email”: “you@company.com”,
“input_type”: “json”,
“input_data”: {
“replace_with”: “lead data matching the supported JSON schema”
},
“industry_profile_type”: “REAL_ESTATE_INVESTORS”,
“customer_request_id”: “request-2026-001”
}

{
“email”: “you@company.com”,
“input_type”: “json”,
“input_data”: {
“replace_with”: “lead data matching the supported JSON schema”
},
“industry_profile_type”: “REAL_ESTATE_INVESTORS”,
“customer_request_id”: “request-2026-001”
}

Input Methods and Required Columns

Input Methods and Required Columns

Input Methods and Required Columns

For file-based input, provide a fetchable file URL containing the lead dataset. For inline JSON input, provide lead data directly in input_data. Required columns depend on the selected industry profile and must match the expected schema exactly.

For file-based input, provide a fetchable file URL containing the lead dataset. For inline JSON input, provide lead data directly in input_data. Required columns depend on the selected industry profile and must match the expected schema exactly.

For file-based input, provide a fetchable file URL containing the lead dataset. For inline JSON input, provide lead data directly in input_data. Required columns depend on the selected industry profile and must match the expected schema exactly.

•

owner_full_name

owner_full_name

owner_full_name

Required. Full name of the property owner.

Required. Full name of the property owner.

Required. Full name of the property owner.

•

mail_street_address

mail_street_address

mail_street_address

Required. Mailing street address.

Required. Mailing street address.

Required. Mailing street address.

•

mail_city

mail_city

mail_city

Required. Mailing city.

Required. Mailing city.

Required. Mailing city.

•

mail_state

mail_state

mail_state

Required. Mailing state.

Required. Mailing state.

Required. Mailing state.

•

mail_zip_code

mail_zip_code

mail_zip_code

Required. Mailing ZIP code.

Required. Mailing ZIP code.

Required. Mailing ZIP code.

•

Property_zip_code

Property_zip_code

Property_zip_code

Industry-specific. Required for Real Estate Investors where applicable.

Industry-specific. Required for Real Estate Investors where applicable.

Industry-specific. Required for Real Estate Investors where applicable.

•

Additional fields may be required depending on the selected industry profile and enrichment workflow.

Additional fields may be required depending on the selected industry profile and enrichment workflow.

Additional fields may be required depending on the selected industry profile and enrichment workflow.

INPUT METHODS

Copy

Copy

Copy

1. File-based input
input_type: “url”
file_url: “https://…/leads.csv”

2. Inline JSON input
input_type: “json”
input_data: { … }

1. File-based input
input_type: “url”
file_url: “https://…/leads.csv”

2. Inline JSON input
input_type: “json”
input_data: { … }

1. File-based input
input_type: “url”
file_url: “https://…/leads.csv”

2. Inline JSON input
input_type: “json”
input_data: { … }

REAL ESTATE INVESTORS

Copy

Copy

Copy

To process leads for real estate investors, set:

“industry_profile_type”: “REAL_ESTATE_INVESTORS”

Then ensure the payload contains the required fields for that profile.

To process leads for real estate investors, set:

“industry_profile_type”: “REAL_ESTATE_INVESTORS”

Then ensure the payload contains the required fields for that profile.

To process leads for real estate investors, set:

“industry_profile_type”: “REAL_ESTATE_INVESTORS”

Then ensure the payload contains the required fields for that profile.

Success Response and Statuses

Success Response and Statuses

Success Response and Statuses

A successful response means processing has been initiated. It does not necessarily mean scoring and enrichment have completed. Use /file-status with the returned status-check token to track progress.

A successful response means processing has been initiated. It does not necessarily mean scoring and enrichment have completed. Use /file-status with the returned status-check token to track progress.

A successful response means processing has been initiated. It does not necessarily mean scoring and enrichment have completed. Use /file-status with the returned status-check token to track progress.

•

msg

msg

msg

Message describing the result of the submission.

Message describing the result of the submission.

Message describing the result of the submission.

•

data.token

data.token

data.token

Token used to check processing status through /file-status.

Token used to check processing status through /file-status.

Token used to check processing status through /file-status.

•

data.file_upload_identifier

data.file_upload_identifier

data.file_upload_identifier

Unique identifier associated with the processing request.

Unique identifier associated with the processing request.

Unique identifier associated with the processing request.

•

data.status

data.status

data.status

Current processing status.

Current processing status.

Current processing status.

•

PROCESSING

PROCESSING

PROCESSING

The request is being processed.

The request is being processed.

The request is being processed.

•

PROCESSED

PROCESSED

PROCESSED

Processing completed successfully.

Processing completed successfully.

Processing completed successfully.

•

ERROR

ERROR

ERROR

Processing encountered an error.

Processing encountered an error.

Processing encountered an error.

•

UNDERREVIEW

UNDERREVIEW

UNDERREVIEW

The request requires review.

The request requires review.

The request requires review.

SUCCESS RESPONSE (200)

Copy

Copy

Copy

{
“msg”: “File processing started”,
“data”: {
“token”: “status-check-token”,
“file_upload_identifier”: “abc123”,
“status”: “PROCESSING”
}
}

{
“msg”: “File processing started”,
“data”: {
“token”: “status-check-token”,
“file_upload_identifier”: “abc123”,
“status”: “PROCESSING”
}
}

{
“msg”: “File processing started”,
“data”: {
“token”: “status-check-token”,
“file_upload_identifier”: “abc123”,
“status”: “PROCESSING”
}
}

Error Responses and Notes

Error Responses and Notes

Error Responses and Notes

The endpoint may return 400 Bad Request for invalid or incomplete input, authentication issues, unsupported configuration values, invalid industry profiles, or submitted data that does not meet the required schema.

The endpoint may return 400 Bad Request for invalid or incomplete input, authentication issues, unsupported configuration values, invalid industry profiles, or submitted data that does not meet the required schema.

The endpoint may return 400 Bad Request for invalid or incomplete input, authentication issues, unsupported configuration values, invalid industry profiles, or submitted data that does not meet the required schema.

•

Duplicate prevention: equivalent file submissions may be detected and returned as duplicates instead of reprocessing.

Duplicate prevention: equivalent file submissions may be detected and returned as duplicates instead of reprocessing.

Duplicate prevention: equivalent file submissions may be detected and returned as duplicates instead of reprocessing.

•

Data overwrite: set overwrite to true when existing duplicate records should be replaced, subject to overwrite rules.

Data overwrite: set overwrite to true when existing duplicate records should be replaced, subject to overwrite rules.

Data overwrite: set overwrite to true when existing duplicate records should be replaced, subject to overwrite rules.

•

Asynchronous processing: use /file-status or the configured callback URL to track completion.

Asynchronous processing: use /file-status or the configured callback URL to track completion.

Asynchronous processing: use /file-status or the configured callback URL to track completion.

•

Request tracking: use customer_request_id to map API requests to your internal jobs, batches, or workflows.

Request tracking: use customer_request_id to map API requests to your internal jobs, batches, or workflows.

Request tracking: use customer_request_id to map API requests to your internal jobs, batches, or workflows.

CASE 1: INVALID API KEY

Copy

Copy

Copy

{
“msg”: “Api key is invalid”,
“data”: null
}

{
“msg”: “Api key is invalid”,
“data”: null
}

{
“msg”: “Api key is invalid”,
“data”: null
}

CASE 2: MISSING FILE URL

Copy

Copy

Copy

{
“msg”: “File url is missing”,
“data”: null
}

{
“msg”: “File url is missing”,
“data”: null
}

{
“msg”: “File url is missing”,
“data”: null
}

File Status

The /file-status endpoint enables clients to check the current processing state of a previously submitted file.


To use this endpoint:

  1. Include the authorization token received from the /process-leads response in the Authorization header.

  2. Submit a POST request with the file_upload_identifier (also from /process-leads) and your email address.


Possible File Processing Statuses

  • PROCESSING: The file is currently being processed.

  • UNDERREVIEW: Processing is complete but results are undergoing review. Expect completion within 12 hours.

  • PROCESSED: The file has been successfully processed.

  • ERROR: Processing could not be completed due to one or more issues.

ENDPOINT

file-status

METHOD

POST

Headers

Authorization

token from process-leads API response

HEADERS

{

"Authorization": "token from process-leads API response"

}

Request Body

When sending leads for scoring, your request body should include all relevant lead information. The more data you provide, the more accurate our scoring will be.

file_upload_identifier

The unique identifier is obtained

from the process-leads response

email

email id you used to create an account on Reworked.ai.

REQUEST BODY

{

"file_upload_identifier": "file upload identifier",

"email": "abc@gmail.com" ,

}

Response

Response of the /process-leads api

Status Code

200

file_upload_identifier

unique identifier of your request

RESPONSE

{

"msg": "File is already in process, pls check after sometime",

"data": {

"error_detail"null,

"token": "Auth Token",

"file_upload_identifier": "file upload identifier",

"status":"PROCESSING"

}

}

Response

Response of the /process-leads api

Status Code

200

file_upload_identifier

unique identifier of your request

RESPONSE

{

"msg": "File is under review, it should be processed within the next 12hrs",

"data": {

"error_detail"null,

"token": "Auth Token",

"file_upload_identifier": "file upload identifier",

"status":"UNDERREVIEW"

}

}

Error Cases

Our API includes comprehensive error handling to help you quickly diagnose and resolve issues during integration.

Status Code

401

Status Code

500

CASE 1

{

"msg": "Api key is invalid",

"data": null

}

CASE 2

{

"msg": "Error 103: Requisite columns required to generate a Betty Score is not present. Please contact admin@reworked.ai or call at +1 (888) 557-9675.",

"data": {

"error_detail":"Error 103: Requisite columns required to generate a Betty Score is not present. Please contact admin@reworked.ai or call at +1 888 306 1949."

"status": "ERROR"

}

}

API Flowchart

API Flowchart

Below is the sequence diagram for API initialization:

Client application requests authentication token

Reworked.ai validates credentials and returns JWT

Client sends lead data with the authorization token

Reworked.ai processes and scores the lead

Response with score and insights is returned to client

Below is the sequence diagram for API initialization:

Client application requests authentication token

Reworked.ai validates credentials and returns JWT

Client sends lead data with the authorization token

Reworked.ai processes and scores the lead

Response with score and insights is returned to client

API Sequence Diagram

Below is the sequence diagram for API interactions:

For bulk scoring operations, our API supports large batches of leads efficiently.

Rate Limit: 50,000 records in a file

Opportunities API

Opportunities API

Opportunities API

The Opportunities API lets you generate, purchase and track roofing opportunities by geography and job type. Use count to see what is available in a target area, or buy to purchase a set of qualified opportunities.

The Opportunities API lets you generate, purchase and track roofing opportunities by geography and job type. Use count to see what is available in a target area, or buy to purchase a set of qualified opportunities.

The Opportunities API lets you generate, purchase and track roofing opportunities by geography and job type. Use count to see what is available in a target area, or buy to purchase a set of qualified opportunities.

•

Include the bearer token from /generate-token in the Authorization header.

Include the bearer token from /generate-token in the Authorization header.

Include the bearer token from /generate-token in the Authorization header.

•

Submit a POST request with your email in the headers and the request body fields below.

Submit a POST request with your email in the headers and the request body fields below.

Submit a POST request with your email in the headers and the request body fields below.

•

Poll /api/opportunity-status with the returned id until the status is processed.

Poll /api/opportunity-status with the returned id until the status is processed.

Poll /api/opportunity-status with the returned id until the status is processed.

ENDPOINT

Copy

Copy

Copy

{{base_url}}/api/opportunities

{{base_url}}/api/opportunities

{{base_url}}/api/opportunities

METHOD

Copy

Copy

Copy

POST

POST

POST

HEADERS

Copy

Copy

Copy

{
“email”: “abc@gmail.com”,
“Authorization”: “Bearer <token from /generate-token>“
}

{
“email”: “abc@gmail.com”,
“Authorization”: “Bearer <token from /generate-token>“
}

{
“email”: “abc@gmail.com”,
“Authorization”: “Bearer <token from /generate-token>“
}

Headers

Headers

Headers

•

email

email

email

Your Reworked.ai account email. Required

Your Reworked.ai account email. Required

•

Authorization

Authorization

Authorization

Bearer token from /generate-token. Required

Bearer token from /generate-token. Required

Request Body

Request Body

Request Body

Provide exactly one location mode per request. The type field controls whether you count available opportunities or buy qualified opportunities.

Provide exactly one location mode per request. The type field controls whether you count available opportunities or buy qualified opportunities.

Provide exactly one location mode per request. The type field controls whether you count available opportunities or buy qualified opportunities.

•

type

type

type

count returns the total available; buy purchases opportunities. Required

count returns the total available; buy purchases opportunities. Required

•

location

location

location

One valid location mode. Required

One valid location mode. Required

•

industry_profile_id

industry_profile_id

industry_profile_id

Industry Profile ID. Optional

Industry Profile ID. Optional

•

job_type

job_type

job_type

Type of roofing job, e.g. roof-replacement or roof-rejuvenation. Optional

Type of roofing job, e.g. roof-replacement or roof-rejuvenation. Optional

•

opportunity_count

opportunity_count

opportunity_count

Number to purchase. Required for buy in standard modes; defaults to 100 in radius mode

Number to purchase. Required for buy in standard modes; defaults to 100 in radius mode

•

external_id

external_id

external_id

Your internal reference, returned as-is in responses. Optional

Your internal reference, returned as-is in responses. Optional

•

addons

addons

addons

Array of enrichment or campaign keys. Optional

Array of enrichment or campaign keys. Optional

•

callback

callback

callback

Webhook URL and headers for async result delivery. Optional

Webhook URL and headers for async result delivery. Optional

REQUEST BODY

Copy

Copy

Copy

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“opportunity_count”: 100,
“external_id”: “your-internal-reference-123”,
“addons”: [“roof_area_estimate”],
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“opportunity_count”: 100,
“external_id”: “your-internal-reference-123”,
“addons”: [“roof_area_estimate”],
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“opportunity_count”: 100,
“external_id”: “your-internal-reference-123”,
“addons”: [“roof_area_estimate”],
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

Location Modes

Location Modes

Location Modes

Four mutually exclusive modes. Do not mix fields from different modes.

Four mutually exclusive modes. Do not mix fields from different modes.

Four mutually exclusive modes. Do not mix fields from different modes.

•

Mode 1: Zip Code — zip accepts a 5-digit zip code or an array of zip codes.

Mode 1: Zip Code — zip accepts a 5-digit zip code or an array of zip codes.

Mode 1: Zip Code — zip accepts a 5-digit zip code or an array of zip codes.

•

Mode 2: City + State — city and 2-letter state code are required.

Mode 2: City + State — city and 2-letter state code are required.

Mode 2: City + State — city and 2-letter state code are required.

•

Mode 3: County + State — county and 2-letter state code are required.

Mode 3: County + State — county and 2-letter state code are required.

Mode 3: County + State — county and 2-letter state code are required.

•

Mode 4: Radius — address is required; radius defaults to 1 mile.

Mode 4: Radius — address is required; radius defaults to 1 mile.

Mode 4: Radius — address is required; radius defaults to 1 mile.

LOCATION MODES

Copy

Copy

Copy

{ “zip”: “11742” }
{ “zip”: [“11742”, “11743”] }
{ “city”: “Holtsville”, “state”: “NY” }
{ “county”: “Suffolk”, “state”: “NY” }
{
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100
}

{ “zip”: “11742” }
{ “zip”: [“11742”, “11743”] }
{ “city”: “Holtsville”, “state”: “NY” }
{ “county”: “Suffolk”, “state”: “NY” }
{
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100
}

{ “zip”: “11742” }
{ “zip”: [“11742”, “11743”] }
{ “city”: “Holtsville”, “state”: “NY” }
{ “county”: “Suffolk”, “state”: “NY” }
{
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100
}

Request Examples

Request Examples

Request Examples

Count returns the total opportunities available for an area. Buy with radius can use defaults: 1 mile and 100 opportunities. Every request returns a processing confirmation. Use the returned id with /api/opportunity-status.

Count returns the total opportunities available for an area. Buy with radius can use defaults: 1 mile and 100 opportunities. Every request returns a processing confirmation. Use the returned id with /api/opportunity-status.

Count returns the total opportunities available for an area. Buy with radius can use defaults: 1 mile and 100 opportunities. Every request returns a processing confirmation. Use the returned id with /api/opportunity-status.

COUNT: COUNTY + STATE

Copy

Copy

Copy

{
“type”: “count”,
“county”: “Suffolk”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

{
“type”: “count”,
“county”: “Suffolk”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

{
“type”: “count”,
“county”: “Suffolk”,
“state”: “NY”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”,
“callback”: {
“url”: “https://client.app/webhooks/opportunities”,
“headers”: { “Authorization”: “Bearer callback-secret” }
}
}

BUY: RADIUS (MINIMAL)

Copy

Copy

Copy

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”
}

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”
}

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“industry_profile_id”: “6925605fcc26d50e46737be3”,
“job_type”: “roof-replacement”
}

RESPONSE

Copy

Copy

Copy

{
“msg”: “Opportunities Processing Started”,
“data”: {
“request”: { “…”: “request body contents” },
“response”: {
“id”: “6985e57bad0e7ed8477579b1”,
“status”: “processing”
}
}
}

{
“msg”: “Opportunities Processing Started”,
“data”: {
“request”: { “…”: “request body contents” },
“response”: {
“id”: “6985e57bad0e7ed8477579b1”,
“status”: “processing”
}
}
}

{
“msg”: “Opportunities Processing Started”,
“data”: {
“request”: { “…”: “request body contents” },
“response”: {
“id”: “6985e57bad0e7ed8477579b1”,
“status”: “processing”
}
}
}

Check Opportunity Status

Check Opportunity Status

Check Opportunity Status

Poll this endpoint to track progress and retrieve results. Completed responses differ by request type.

Poll this endpoint to track progress and retrieve results. Completed responses differ by request type.

Poll this endpoint to track progress and retrieve results. Completed responses differ by request type.

•

in_progress — the system is fetching and enriching data.

in_progress — the system is fetching and enriching data.

in_progress — the system is fetching and enriching data.

•

processed — data is ready. For count: total available. For buy: a download URL.

processed — data is ready. For count: total available. For buy: a download URL.

processed — data is ready. For count: total available. For buy: a download URL.

•

failed — an error occurred during processing.

failed — an error occurred during processing.

failed — an error occurred during processing.

ENDPOINT

Copy

Copy

Copy

{{base_url}}/api/opportunity-status

{{base_url}}/api/opportunity-status

{{base_url}}/api/opportunity-status

REQUEST BODY

Copy

Copy

Copy

{ “id”: “6957cdc983c856006ea70d46” }

{ “id”: “6957cdc983c856006ea70d46” }

{ “id”: “6957cdc983c856006ea70d46” }

COUNT: COMPLETED

Copy

Copy

Copy

{
“request”: { “id”: “6985e551ad0e7ed8477579b0” },
“response”: {
“msg”: “Opportunities count fetched successfully”,
“data”: {
“id”: “6985e551ad0e7ed8477579b0”,
“max_opportunities_count”: 84197,
“status”: “processed”
}
}
}

{
“request”: { “id”: “6985e551ad0e7ed8477579b0” },
“response”: {
“msg”: “Opportunities count fetched successfully”,
“data”: {
“id”: “6985e551ad0e7ed8477579b0”,
“max_opportunities_count”: 84197,
“status”: “processed”
}
}
}

{
“request”: { “id”: “6985e551ad0e7ed8477579b0” },
“response”: {
“msg”: “Opportunities count fetched successfully”,
“data”: {
“id”: “6985e551ad0e7ed8477579b0”,
“max_opportunities_count”: 84197,
“status”: “processed”
}
}
}

BUY: COMPLETED

Copy

Copy

Copy

{
“request”: { “id”: “698623bf405b83e9b9e6f083” },
“response”: {
“msg”: “Opportunities Purchased Successfully”,
“data”: {
“id”: “698623bf405b83e9b9e6f083”,
“external_id”: “your-internal-reference-123”,
“max_opportunities_count”: 660,
“file_url”: “https://s3-url…”,
“status”: “processed”
}
}
}

{
“request”: { “id”: “698623bf405b83e9b9e6f083” },
“response”: {
“msg”: “Opportunities Purchased Successfully”,
“data”: {
“id”: “698623bf405b83e9b9e6f083”,
“external_id”: “your-internal-reference-123”,
“max_opportunities_count”: 660,
“file_url”: “https://s3-url…”,
“status”: “processed”
}
}
}

{
“request”: { “id”: “698623bf405b83e9b9e6f083” },
“response”: {
“msg”: “Opportunities Purchased Successfully”,
“data”: {
“id”: “698623bf405b83e9b9e6f083”,
“external_id”: “your-internal-reference-123”,
“max_opportunities_count”: 660,
“file_url”: “https://s3-url…”,
“status”: “processed”
}
}
}

Add-Ons (Roofing)

Add-Ons (Roofing)

Add-Ons (Roofing)

Pass these keys in the addons array to enrich each opportunity or launch a campaign. Add-ons work in all location modes, including radius, and apply to roofing accounts only.

Pass these keys in the addons array to enrich each opportunity or launch a campaign. Add-ons work in all location modes, including radius, and apply to roofing accounts only.

Pass these keys in the addons array to enrich each opportunity or launch a campaign. Add-ons work in all location modes, including radius, and apply to roofing accounts only.

•

roof_area_estimate

roof_area_estimate

roof_area_estimate

Roof area, facets and squares for accurate quoting.

Roof area, facets and squares for accurate quoting.

•

phone_no_append

phone_no_append

phone_no_append

Verified phone number for calling campaigns.

Verified phone number for calling campaigns.

•

email_append

email_append

email_append

Verified email address for digital campaigns.

Verified email address for digital campaigns.

•

roof_type

roof_type

roof_type

Roof material such as asphalt, metal or tile.

Roof material such as asphalt, metal or tile.

•

google_satellite_image

google_satellite_image

google_satellite_image

Standard-resolution Google aerial view.

Standard-resolution Google aerial view.

•

direct_mail_campaign

direct_mail_campaign

direct_mail_campaign

Configurable letter and postcard sequence.

Configurable letter and postcard sequence.

•

digital_ads_campaign

digital_ads_campaign

digital_ads_campaign

Display ads served to purchased households.

Display ads served to purchased households.

BUY: CITY + STATE WITH ADD-ONS

Copy

Copy

Copy

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“opportunity_count”: 100,
“addons”: [“roof_area_estimate”, “phone_no_append”, “email_append”],
“job_type”: “roof-replacement”
}

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“opportunity_count”: 100,
“addons”: [“roof_area_estimate”, “phone_no_append”, “email_append”],
“job_type”: “roof-replacement”
}

{
“type”: “buy”,
“city”: “Holtsville”,
“state”: “NY”,
“opportunity_count”: 100,
“addons”: [“roof_area_estimate”, “phone_no_append”, “email_append”],
“job_type”: “roof-replacement”
}

BUY: RADIUS WITH OVERRIDES

Copy

Copy

Copy

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100,
“job_type”: “roof-replacement”,
“addons”: [“roof_area_estimate”, “phone_no_append”]
}

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100,
“job_type”: “roof-replacement”,
“addons”: [“roof_area_estimate”, “phone_no_append”]
}

{
“type”: “buy”,
“address”: “123 Main St, Holtsville, NY 11742”,
“radius”: 2,
“opportunity_count”: 100,
“job_type”: “roof-replacement”,
“addons”: [“roof_area_estimate”, “phone_no_append”]
}

Campaign Add-On Requirements

Campaign Add-On Requirements

Campaign Add-On Requirements

Both campaign add-ons need branding on file. Call GET /api/branding and confirm missing_for_digital_ads is empty before purchasing. direct_mail_campaign needs complete mailing info and a valid template_id. digital_ads_campaign needs at least 1,000 opportunities and a complete brand kit.

Both campaign add-ons need branding on file. Call GET /api/branding and confirm missing_for_digital_ads is empty before purchasing. direct_mail_campaign needs complete mailing info and a valid template_id. digital_ads_campaign needs at least 1,000 opportunities and a complete brand kit.

Both campaign add-ons need branding on file. Call GET /api/branding and confirm missing_for_digital_ads is empty before purchasing. direct_mail_campaign needs complete mailing info and a valid template_id. digital_ads_campaign needs at least 1,000 opportunities and a complete brand kit.

•

Finding template_id: send a direct_mail_campaign order with no template_id. The 400 response lists available templates.

Finding template_id: send a direct_mail_campaign order with no template_id. The 400 response lists available templates.

Finding template_id: send a direct_mail_campaign order with no template_id. The 400 response lists available templates.

CASE 1: BELOW DIGITAL ADS MINIMUM

Copy

Copy

Copy

// Request
{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 50,
“addons”: [“digital_ads_campaign”]
}

// Response (400)
{
“response”: {
“msg”: “Digital Ads requires at least 1000 opportunities (got 50).”
}
}

// Request
{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 50,
“addons”: [“digital_ads_campaign”]
}

// Response (400)
{
“response”: {
“msg”: “Digital Ads requires at least 1000 opportunities (got 50).”
}
}

// Request
{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 50,
“addons”: [“digital_ads_campaign”]
}

// Response (400)
{
“response”: {
“msg”: “Digital Ads requires at least 1000 opportunities (got 50).”
}
}

CASE 2: MISSING template_id

Copy

Copy

Copy

{
“response”: {
“msg”: “Missing template_id in request. Please provide a template_id to use the Direct Mail Campaign addon.”,
“data”: {
“availableTemplates”: [
{ “template_id”: “template_1”, “required_fields”: [ … ] },
{ “template_id”: “template_2”, “required_fields”: [ … ] }
]
}
}
}

{
“response”: {
“msg”: “Missing template_id in request. Please provide a template_id to use the Direct Mail Campaign addon.”,
“data”: {
“availableTemplates”: [
{ “template_id”: “template_1”, “required_fields”: [ … ] },
{ “template_id”: “template_2”, “required_fields”: [ … ] }
]
}
}
}

{
“response”: {
“msg”: “Missing template_id in request. Please provide a template_id to use the Direct Mail Campaign addon.”,
“data”: {
“availableTemplates”: [
{ “template_id”: “template_1”, “required_fields”: [ … ] },
{ “template_id”: “template_2”, “required_fields”: [ … ] }
]
}
}
}

Configuring the Mail Sequence

Configuring the Mail Sequence

Configuring the Mail Sequence

By default direct_mail_campaign sends a letter, then a postcard seven days later. Send touch_config to choose pieces, mail class and spacing. One to three touches are supported.

By default direct_mail_campaign sends a letter, then a postcard seven days later. Send touch_config to choose pieces, mail class and spacing. One to three touches are supported.

By default direct_mail_campaign sends a letter, then a postcard seven days later. Send touch_config to choose pieces, mail class and spacing. One to three touches are supported.

•

campaign_type

campaign_type

campaign_type

letter_only, postcard_only, 2_touch, or 3_touch. Defaults to 2_touch.

letter_only, postcard_only, 2_touch, or 3_touch. Defaults to 2_touch.

•

touches[].format

touches[].format

touches[].format

letter or postcard.

letter or postcard.

•

touches[].delivery_class

touches[].delivery_class

touches[].delivery_class

first_class or standard.

first_class or standard.

•

touches[].gap_days

touches[].gap_days

touches[].gap_days

Integer days after the previous touch. Defaults to 7.

Integer days after the previous touch. Defaults to 7.

REQUEST BODY

Copy

Copy

Copy

{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 1000,
“addons”: [“direct_mail_campaign”],
“template_id”: “tmpl_…”,
“touch_config”: {
“campaign_type”: “3_touch”,
“touches”: [
{ “format”: “letter”, “delivery_class”: “first_class” },
{ “format”: “postcard”, “delivery_class”: “first_class”, “gap_days”: 7 },
{ “format”: “postcard”, “delivery_class”: “standard”, “gap_days”: 14 }
]
}
}

{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 1000,
“addons”: [“direct_mail_campaign”],
“template_id”: “tmpl_…”,
“touch_config”: {
“campaign_type”: “3_touch”,
“touches”: [
{ “format”: “letter”, “delivery_class”: “first_class” },
{ “format”: “postcard”, “delivery_class”: “first_class”, “gap_days”: 7 },
{ “format”: “postcard”, “delivery_class”: “standard”, “gap_days”: 14 }
]
}
}

{
“type”: “buy”,
“zip”: “11742”,
“opportunity_count”: 1000,
“addons”: [“direct_mail_campaign”],
“template_id”: “tmpl_…”,
“touch_config”: {
“campaign_type”: “3_touch”,
“touches”: [
{ “format”: “letter”, “delivery_class”: “first_class” },
{ “format”: “postcard”, “delivery_class”: “first_class”, “gap_days”: 7 },
{ “format”: “postcard”, “delivery_class”: “standard”, “gap_days”: 14 }
]
}
}

Error Cases

Error Cases

Error Cases

Unknown or malformed input is always rejected, never silently ignored.

Unknown or malformed input is always rejected, never silently ignored.

Unknown or malformed input is always rejected, never silently ignored.

•

Status Code 400 — unrecognised add-on key.

Status Code 400 — unrecognised add-on key.

Status Code 400 — unrecognised add-on key.

•

Status Code 400 — addons sent as a bare string instead of a JSON array.

Status Code 400 — addons sent as a bare string instead of a JSON array.

Status Code 400 — addons sent as a bare string instead of a JSON array.

•

Status Code 400 — add-ons used on a non-roofing industry type.

Status Code 400 — add-ons used on a non-roofing industry type.

Status Code 400 — add-ons used on a non-roofing industry type.

•

Status Code 400 — missing or invalid template_id, incomplete mailing info, or malformed touch_config.

Status Code 400 — missing or invalid template_id, incomplete mailing info, or malformed touch_config.

Status Code 400 — missing or invalid template_id, incomplete mailing info, or malformed touch_config.

UNKNOWN ADD-ON

Copy

Copy

Copy

{
“response”: {
“msg”: “Unsupported add-on: “<key>“. Supported: roof_area_estimate, phone_no_append, …”
}
}

{
“response”: {
“msg”: “Unsupported add-on: “<key>“. Supported: roof_area_estimate, phone_no_append, …”
}
}

{
“response”: {
“msg”: “Unsupported add-on: “<key>“. Supported: roof_area_estimate, phone_no_append, …”
}
}

Branding API

Branding API

Branding API

The Branding API stores the company identity used across both direct mail and digital ads. Shared fields — company name, phone, website, landing URL, logo, licence and return address — feed both products. Brand colour, CTA label and banner copy apply to digital ads only.

The Branding API stores the company identity used across both direct mail and digital ads. Shared fields — company name, phone, website, landing URL, logo, licence and return address — feed both products. Brand colour, CTA label and banner copy apply to digital ads only.

The Branding API stores the company identity used across both direct mail and digital ads. Shared fields — company name, phone, website, landing URL, logo, licence and return address — feed both products. Brand colour, CTA label and banner copy apply to digital ads only.

•

Digital ad campaigns are held until branding is complete, so this endpoint is a prerequisite for the direct_mail_campaign and digital ads add-ons.

Digital ad campaigns are held until branding is complete, so this endpoint is a prerequisite for the direct_mail_campaign and digital ads add-ons.

Digital ad campaigns are held until branding is complete, so this endpoint is a prerequisite for the direct_mail_campaign and digital ads add-ons.

SAVE BRANDING

Copy

Copy

Copy

POST {{base_url}}/api/branding

POST {{base_url}}/api/branding

POST {{base_url}}/api/branding

GET BRANDING

Copy

Copy

Copy

GET {{base_url}}/api/branding

GET {{base_url}}/api/branding

GET {{base_url}}/api/branding

REQUEST HEADERS

Copy

Copy

Copy

{
“Authorization”: “Bearer <token from /generate-token>“
}

{
“Authorization”: “Bearer <token from /generate-token>“
}

{
“Authorization”: “Bearer <token from /generate-token>“
}

Save Branding

Save Branding

Save Branding

All fields are optional. Omitting a field leaves its current value unchanged. Logo uploads are limited by the 1MB request body limit; base64 encoding means the practical image ceiling is roughly 700KB.

All fields are optional. Omitting a field leaves its current value unchanged. Logo uploads are limited by the 1MB request body limit; base64 encoding means the practical image ceiling is roughly 700KB.

All fields are optional. Omitting a field leaves its current value unchanged. Logo uploads are limited by the 1MB request body limit; base64 encoding means the practical image ceiling is roughly 700KB.

•

company_name

company_name

company_name

String, max 40. Printed on mail; carrier return-address limit.

String, max 40. Printed on mail; carrier return-address limit.

•

company_phone

company_phone

company_phone

String, max 30. Contact number shown on mailers and ads.

String, max 30. Contact number shown on mailers and ads.

•

company_website

company_website

company_website

String, max 200. Absolute http(s) URL.

String, max 200. Absolute http(s) URL.

•

landing_url

landing_url

landing_url

String, max 200. Destination for QR code and ad clicks.

String, max 200. Destination for QR code and ad clicks.

•

license_number

license_number

license_number

String, max 50. Contractor licence where required.

String, max 50. Contractor licence where required.

•

name_and_role

name_and_role

name_and_role

String, max 60, e.g. Andrew Sellers, Owner.

String, max 60, e.g. Andrew Sellers, Owner.

•

return_address_*

return_address_*

return_address_*

Street, city, state and zip for the return address.

Street, city, state and zip for the return address.

•

logo_base64

logo_base64

logo_base64

Raw base64 or data:image/png;base64,… URI. About 700KB practical ceiling.

Raw base64 or data:image/png;base64,… URI. About 700KB practical ceiling.

•

logo_url

logo_url

logo_url

Alternative to logo_base64; ignored if logo_base64 is present.

Alternative to logo_base64; ignored if logo_base64 is present.

•

brand_color

brand_color

brand_color

Hex, e.g. #0A5C36. Required before digital ads can run.

Hex, e.g. #0A5C36. Required before digital ads can run.

•

cta_label

cta_label

cta_label

String, max 30. Ad call-to-action, e.g. free inspection.

String, max 30. Ad call-to-action, e.g. free inspection.

•

heading

heading

heading

String, max 50. Ad banner heading. Blank uses approved default.

String, max 50. Ad banner heading. Blank uses approved default.

•

sub_heading

sub_heading

sub_heading

String, max 65. Ad banner sub-heading.

String, max 65. Ad banner sub-heading.

•

show_stamp

show_stamp

show_stamp

Boolean. Draws the FREE INSPECTION / CASH OFFER seal; defaults to on.

Boolean. Draws the FREE INSPECTION / CASH OFFER seal; defaults to on.

REQUEST BODY

Copy

Copy

Copy

{
“company_name”: “Acme Roofing”,
“company_phone”: “843-438-6674”,
“company_website”: “https://acmeroofing.com”,
“landing_url”: “https://acmeroofing.com/contact”,
“license_number”: “KRR 13-115046”,
“return_address_line1”: “339 Empyrean Circle”,
“return_address_city”: “Myrtle Beach”,
“return_address_state”: “SC”,
“return_address_zip”: “29588”,
“logo_base64”: “data:image/png;base64,iVBORw0KGgoAAAANS…”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“heading”: “Get your free roof inspection today!”
}

{
“company_name”: “Acme Roofing”,
“company_phone”: “843-438-6674”,
“company_website”: “https://acmeroofing.com”,
“landing_url”: “https://acmeroofing.com/contact”,
“license_number”: “KRR 13-115046”,
“return_address_line1”: “339 Empyrean Circle”,
“return_address_city”: “Myrtle Beach”,
“return_address_state”: “SC”,
“return_address_zip”: “29588”,
“logo_base64”: “data:image/png;base64,iVBORw0KGgoAAAANS…”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“heading”: “Get your free roof inspection today!”
}

{
“company_name”: “Acme Roofing”,
“company_phone”: “843-438-6674”,
“company_website”: “https://acmeroofing.com”,
“landing_url”: “https://acmeroofing.com/contact”,
“license_number”: “KRR 13-115046”,
“return_address_line1”: “339 Empyrean Circle”,
“return_address_city”: “Myrtle Beach”,
“return_address_state”: “SC”,
“return_address_zip”: “29588”,
“logo_base64”: “data:image/png;base64,iVBORw0KGgoAAAANS…”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“heading”: “Get your free roof inspection today!”
}

Success and Validation

Success and Validation

Success and Validation

missing_for_digital_ads lists fields still required before digital ad campaigns can run. An empty array means branding is complete. Values are never silently truncated; over-length values fail the request so they are corrected before printed mail.

missing_for_digital_ads lists fields still required before digital ad campaigns can run. An empty array means branding is complete. Values are never silently truncated; over-length values fail the request so they are corrected before printed mail.

missing_for_digital_ads lists fields still required before digital ad campaigns can run. An empty array means branding is complete. Values are never silently truncated; over-length values fail the request so they are corrected before printed mail.

•

Success Response: 200 — branding saved and current readiness returned.

Success Response: 200 — branding saved and current readiness returned.

Success Response: 200 — branding saved and current readiness returned.

•

Error Response: 400 — every rejected field is returned at once for batch correction.

Error Response: 400 — every rejected field is returned at once for batch correction.

Error Response: 400 — every rejected field is returned at once for batch correction.

SUCCESS RESPONSE (200)

Copy

Copy

Copy

{
“request”: { “…”: “submitted values, logo omitted” },
“response”: {
“msg”: “Branding saved”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“company_logo_key”: “you@company.com/direct_mail_logos/logo_1788161794189.png”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“updated_at”: “2026-08-31T09:12:44.201Z”,
“missing_for_digital_ads”: []
}
}
}

{
“request”: { “…”: “submitted values, logo omitted” },
“response”: {
“msg”: “Branding saved”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“company_logo_key”: “you@company.com/direct_mail_logos/logo_1788161794189.png”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“updated_at”: “2026-08-31T09:12:44.201Z”,
“missing_for_digital_ads”: []
}
}
}

{
“request”: { “…”: “submitted values, logo omitted” },
“response”: {
“msg”: “Branding saved”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“company_logo_key”: “you@company.com/direct_mail_logos/logo_1788161794189.png”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“updated_at”: “2026-08-31T09:12:44.201Z”,
“missing_for_digital_ads”: []
}
}
}

ERROR RESPONSE (400)

Copy

Copy

Copy

{
“request”: { “…”: “submitted values” },
“response”: {
“msg”: “company_name exceeds 40 characters; brand_color must be a hex colour such as #0A5C36”,
“data”: {
“errors”: [
{ “field”: “company_name”, “msg”: “company_name exceeds 40 characters”, “max”: 40, “got”: 49 },
{ “field”: “brand_color”, “msg”: “brand_color must be a hex colour such as #0A5C36” }
]
}
}
}

{
“request”: { “…”: “submitted values” },
“response”: {
“msg”: “company_name exceeds 40 characters; brand_color must be a hex colour such as #0A5C36”,
“data”: {
“errors”: [
{ “field”: “company_name”, “msg”: “company_name exceeds 40 characters”, “max”: 40, “got”: 49 },
{ “field”: “brand_color”, “msg”: “brand_color must be a hex colour such as #0A5C36” }
]
}
}
}

{
“request”: { “…”: “submitted values” },
“response”: {
“msg”: “company_name exceeds 40 characters; brand_color must be a hex colour such as #0A5C36”,
“data”: {
“errors”: [
{ “field”: “company_name”, “msg”: “company_name exceeds 40 characters”, “max”: 40, “got”: 49 },
{ “field”: “brand_color”, “msg”: “brand_color must be a hex colour such as #0A5C36” }
]
}
}
}

Get Branding

Get Branding

Get Branding

Returns the current branding values plus missing_for_digital_ads. Use this to confirm a sync or check readiness before purchasing opportunities with the digital ads add-on.

Returns the current branding values plus missing_for_digital_ads. Use this to confirm a sync or check readiness before purchasing opportunities with the digital ads add-on.

Returns the current branding values plus missing_for_digital_ads. Use this to confirm a sync or check readiness before purchasing opportunities with the digital ads add-on.

•

200

200

200

Saved / fetched successfully.

Saved / fetched successfully.

•

400

400

400

One or more fields rejected; see data.errors. Also unreadable or oversized logo.

One or more fields rejected; see data.errors. Also unreadable or oversized logo.

•

401

401

401

Invalid or expired authorization token.

Invalid or expired authorization token.

•

404

404

404

Account not found for the token’s email.

Account not found for the token’s email.

•

413

413

413

Request body exceeded 1MB — usually oversized logo_base64.

Request body exceeded 1MB — usually oversized logo_base64.

•

422

422

422

A field was the wrong JSON type, e.g. show_stamp sent as a string.

A field was the wrong JSON type, e.g. show_stamp sent as a string.

GET BRANDING

Copy

Copy

Copy

GET {{base_url}}/api/branding

GET {{base_url}}/api/branding

GET {{base_url}}/api/branding

READINESS CHECK

Copy

Copy

Copy

{
“response”: {
“msg”: “Branding fetched”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“missing_for_digital_ads”: []
}
}
}

{
“response”: {
“msg”: “Branding fetched”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“missing_for_digital_ads”: []
}
}
}

{
“response”: {
“msg”: “Branding fetched”,
“data”: {
“company_name”: “Acme Roofing”,
“landing_url”: “https://acmeroofing.com/contact”,
“brand_color”: “#0A5C36”,
“cta_label”: “free inspection”,
“missing_for_digital_ads”: []
}
}
}

Implementation Notes

Implementation Notes

Implementation Notes

Both APIs follow an asynchronous request-response pattern: authenticate, submit a request, track progress or provide a callback URL, then retrieve results once status reaches PROCESSED or processed.

Both APIs follow an asynchronous request-response pattern: authenticate, submit a request, track progress or provide a callback URL, then retrieve results once status reaches PROCESSED or processed.

Both APIs follow an asynchronous request-response pattern: authenticate, submit a request, track progress or provide a callback URL, then retrieve results once status reaches PROCESSED or processed.

•

Async Handling: requests process in the background; poll when no callback URL is provided.

Async Handling: requests process in the background; poll when no callback URL is provided.

Async Handling: requests process in the background; poll when no callback URL is provided.

•

Token Expiry: JWT tokens expire after 48 hours. Generate a new token before expiry.

Token Expiry: JWT tokens expire after 48 hours. Generate a new token before expiry.

Token Expiry: JWT tokens expire after 48 hours. Generate a new token before expiry.

•

Duplicate Prevention: Lead Scoring detects duplicate file submissions rather than reprocessing.

Duplicate Prevention: Lead Scoring detects duplicate file submissions rather than reprocessing.

Duplicate Prevention: Lead Scoring detects duplicate file submissions rather than reprocessing.

•

Location Exclusivity: Opportunities requests must use only one location mode.

Location Exclusivity: Opportunities requests must use only one location mode.

Location Exclusivity: Opportunities requests must use only one location mode.

•

Radius Defaults: radius defaults to 1 mile and opportunity_count defaults to 100.

Radius Defaults: radius defaults to 1 mile and opportunity_count defaults to 100.

Radius Defaults: radius defaults to 1 mile and opportunity_count defaults to 100.

•

Rate Limits: Lead Scoring supports up to 50,000 records per file.

Rate Limits: Lead Scoring supports up to 50,000 records per file.

Rate Limits: Lead Scoring supports up to 50,000 records per file.

API WORKFLOW

Copy

Copy

Copy

1. Authenticate with /generate-token
2. Submit to /process-leads or /opportunities
3. Track via /file-status or /opportunity-status
4. Retrieve results when status is PROCESSED/processed

1. Authenticate with /generate-token
2. Submit to /process-leads or /opportunities
3. Track via /file-status or /opportunity-status
4. Retrieve results when status is PROCESSED/processed

1. Authenticate with /generate-token
2. Submit to /process-leads or /opportunities
3. Track via /file-status or /opportunity-status
4. Retrieve results when status is PROCESSED/processed

SUPPORT

Copy

Copy

Copy

For API key provisioning, base URL configuration, or technical support:

admin@reworked.ai
+1 (888) 557-9675

Or contact your Reworked.ai representative.

For API key provisioning, base URL configuration, or technical support:

admin@reworked.ai
+1 (888) 557-9675

Or contact your Reworked.ai representative.

For API key provisioning, base URL configuration, or technical support:

admin@reworked.ai
+1 (888) 557-9675

Or contact your Reworked.ai representative.

© 2026 Reworked AI. All rights reserved.

© 2026 Reworked AI. All rights reserved.

© 2026 Reworked AI. All rights reserved.