Back to top

Forward Financing API

Our Partner API is designed to allow our business partners to submit potential deals automatically from their system to ours and receive information on the statuses of their deals.

Host

This is the base URL for this API: https://api.staging.forwardfinancing.com/

Authentication

You will need to contact us to get your API key. This key must be included in all requests to the Partner API. The HTTP header key is api_key and the value is the one provided by us.

If you omit the api_key header or provide an incorrect value, the HTTP status code of the response will be 401 Unauthorized.

HTTPS

Since your API requests will contain sensitive personal information about our customers, you must use SSL (HTTPS). To discourage insecure API requests, the response code will be 403 Forbidden for all requests made over HTTP.

Rate Limiting

We impose a rate limit per user of 1 request per second. If you exceed this rate of requests, the response code will be 429 Too Many Requests. If you need to exceed this limit for some reason, please let us know!

Lead Submission API

Submit a New Lead

POST/v1/lead

Submit a new lead directly to our system in the JSON format specified.

A unique reference_id must be submitted in the request and it should represent your internal ID for that submission.

Example URI

POST /v1/lead
Request  Successful
HideShow
Headers
Content-Type: application/json
api_key: Your_API_Key
Body
{
  "lead": {
    "contacts_attributes": [
      {
        "first_name": "Erlich",
        "last_name": "Bachman",
        "email": "erlich@piedpiper.com",
        "title": "COO and Spiritual Advisor",
        "born_on": "2015-01-01",
        "home_phone": "6176781000",
        "cell_phone": "6176781000",
        "ssn": "234345566",
        "ownership_date": "2015-01-01",
        "current_address_attributes": {
          "street1": "36 Bromfield St",
          "street2": "Second Floor",
          "city": "Boston",
          "state": "MA",
          "zip": "00112"
        }
      }
    ],
    "account_attributes": {
      "entity_type": "Limited Liability Company (LLC)",
      "name": "Pied Piper",
      "started_on": "2015-01-01",
      "legal_name": "Pied Piper LLC",
      "phone": "6176781000",
      "email": "support@piedpiper.com",
      "website": "https://www.piedpiper.com/",
      "fein": "000000000",
      "monthly_revenue": "Less than $5,000",
      "industry_name": "Compression Algorithms",
      "current_address_attributes": {
        "street1": "36 Bromfield St",
        "street2": "Second Floor",
        "city": "Boston",
        "state": "MA",
        "zip": "00112"
      }
    },
    "loan_attributes": {
      "company_name": "Wells Fargo",
      "daily_payment_amount": 25,
      "balance": 15000.23
    },
    "application_attributes": {
      "has_current_loan": true,
      "applicant_is_owner": true,
      "loan_use": "Debt Refinancing",
      "capital_needed": "50000",
      "owner_1_percent_ownership": 56,
      "owner_2_percent_ownership": 9,
      "reference_id": "ANYTHING_YOUWANT_AS_A_STRING",
      "notes": "We think this is a great deal!"
    },
    "meta": {
      "custom_field": "custom data",
      "campaign_id": "CAMP-2026-Q2"
    }
  }
}
Response  201
HideShow

If your request is successful, you will receive HTTP status code 201 Created. The response body will contain a success message, and an ID for your submission, which will be used later for submitting attachments. For example

Headers
Content-Type: application/json
Body
{
  "message": "Your lead was successfully created.",
  "id": "YOUR_LEAD_ID_HERE"
}
Request  Missing Info
HideShow
Headers
Content-Type: application/json
api_key: Your_API_Key
Body
{
  "lead": {
    "contacts_attributes": [
      {
        "first_name": "Erlich",
        "last_name": "Bachman",
        "email": "erlich@piedpiper.com",
        "title": "COO and Spiritual Advisor",
        "born_on": "2015-01-01",
        "home_phone": "6176781000",
        "cell_phone": "6176781000",
        "ssn": "234345566",
        "ownership_date": "2015-01-01"
      }
    ],
    "account_attributes": {
      "entity_type": "Limited Liability Company (LLC)",
      "name": "Pied Piper",
      "started_on": "2015-01-01",
      "legal_name": "Pied Piper LLC",
      "phone": "6176781000",
      "email": "support@piedpiper.com",
      "website": "https://www.piedpiper.com/",
      "fein": "000000000",
      "monthly_revenue": "Less than $5,000",
      "industry_name": "Compression Algorithms",
      "current_address_attributes": {
        "street1": "36 Bromfield St",
        "street2": "Second Floor",
        "city": "Boston",
        "state": "MA",
        "zip": "00112"
      }
    },
    "loan_attributes": {
      "company_name": "Wells Fargo",
      "daily_payment_amount": 25,
      "balance": 15000.23
    },
    "application_attributes": {
      "has_current_loan": true,
      "applicant_is_owner": true,
      "loan_use": "Debt Refinancing",
      "capital_needed": "50000",
      "owner_1_percent_ownership": 56,
      "owner_2_percent_ownership": 9,
      "reference_id": "ANYTHING_YOUWANT_AS_A_STRING",
      "notes": "We think this is a great deal!"
    }
  }
}
Response  422
HideShow

If your request is unsuccessful, for example if the JSON is invalid or certain required attributes are missing, you will receive HTTP status code 422 Unprocessable Entity. The response body may contain information about what part of your request was invalid in JSON format, for example:

Headers
Content-Type: application/json
Body
{
  "errors": {
    "contacts_attributes": [
      "Must provide address"
    ]
  }
}
Request  Non-Unique Reference ID
HideShow
Headers
Content-Type: application/json
api_key: Your_API_Key
Body
{
  "lead": {
    "contacts_attributes": [
      {
        "first_name": "Erlich",
        "last_name": "Bachman",
        "email": "erlich@piedpiper.com",
        "title": "COO and Spiritual Advisor",
        "born_on": "2015-01-01",
        "home_phone": "6176781000",
        "cell_phone": "6176781000",
        "ssn": "234345566",
        "ownership_date": "2015-01-01"
      }
    ],
    "account_attributes": {
      "entity_type": "Limited Liability Company (LLC)",
      "name": "Pied Piper",
      "started_on": "2015-01-01",
      "legal_name": "Pied Piper LLC",
      "phone": "6176781000",
      "email": "support@piedpiper.com",
      "website": "https://www.piedpiper.com/",
      "fein": "000000000",
      "monthly_revenue": "Less than $5,000",
      "industry_name": "Compression Algorithms",
      "current_address_attributes": {
        "street1": "36 Bromfield St",
        "street2": "Second Floor",
        "city": "Boston",
        "state": "MA",
        "zip": "00112"
      }
    },
    "loan_attributes": {
      "company_name": "Wells Fargo",
      "daily_payment_amount": 25,
      "balance": 15000.23
    },
    "application_attributes": {
      "has_current_loan": true,
      "applicant_is_owner": true,
      "loan_use": "Debt Refinancing",
      "capital_needed": "50000",
      "owner_1_percent_ownership": 56,
      "owner_2_percent_ownership": 9,
      "reference_id": "THIS_ISNT_UNIQUE",
      "notes": "We think this is a great deal!"
    }
  }
}
Response  422
HideShow

You may also receive an HTTP status code of 422 Unprocessable Entity if you have submitted a reference_id that you have used in the past. In that case you will see a similar JSON response, like:

Headers
Content-Type: application/json
Body
{
  "message": "Reference ID is not unique."
}

Submit an Attachment File

POST/v1/attachment?filename={filename}&lead_id={lead_id}&encoded={encoded}

This endpoint is for uploading documents associated with your recently created lead.

Send your attachment file as a raw binary.

The request body should contain the binary of the file you want to upload. In most languages, you can accomplish this by reading the file contents into memory and then outputting them into your request body as binary or a string.

You may only submit one attachment per request. To submit more than one attachment, send each attachment in its own request.

If for some reason your system does not allow you to send a binary request body, you can Base 64 encode the binary into a string. If you choose this option, you must indicate that the body is encoded by passing encoded=true in the URL parameters. Be sure to use strict Base 64 encoding, which encodes new line (\n) characters.

Example URI

POST /v1/attachment?filename=filename&lead_id=lead_id&encoded=encoded
URI Parameters
HideShow
filename
string (required) 

The desired filename in our system for the attachment you are uploading. For example “bank_statement.pdf”

lead_id
string (required) 

Which of your previously submitted leads the attachment is associated with. The lead id can be found in the response to the leads endpoint.

encoded
boolean (optional) 

If for some reason, your system does not allow you to send a binary request body, you can Base 64 encode the binary into a string. If you choose this option, you must indicate the body is encoded by passing encoded=true in the URL parameters. Be sure to use strict Base 64 encoding, which encodes new line (\n) characters.

Request
HideShow
Headers
api_key: Your_API_KEY
Body
Binary of your file
Response  202
HideShow
Body
{
  "message": "Your attachment was received and is being processed"
}

Submit an Attachment From a URL

POST/v1/attachment

The same endpoint can be used to submit the URL of an attachment rather than the raw binary.

If your attachments can be found at a public URL, you can submit the URL. If it is not a public URL, we will not be able to access your file.

You may only submit one attachment per request. To submit more than one attachments, send each attachment in its own request.

Example URI

POST /v1/attachment
Request
HideShow
Headers
Content-Type: application/json
api_key: Your_API_KEY
Body
{
  "attachment_url": "https://yourwebsite.com/files/some_attachment.pdf",
  "filename": "bank_statement.pdf",
  "lead_id": "QTEQ.YJNyDzbMP0YX0D7qQr7PZcn7CU2E.TIIvFdZlr._ps.FDvDvwqGzI-c5FQ"
}
Response  202
HideShow
Body
{
  "message": "Your attachment was received and is being processed"
}

Upload a Closing Attachment File

POST/v1/submissions/{lead_id}/closing_attachment?filename={filename}&document_tags[]=&document_tags[]=&encoded={encoded}

This endpoint allows you to upload a stipulation, or any document related to the Closing Department, for a deal you have already submitted.

Send your attachment file as a raw binary in the request body. You may only submit one attachment per request. To upload more than one document, send each attachment in its own request.

If for some reason your system does not allow you to send a binary request body, you can Base 64 encode the binary into a string. If you choose this option, you must indicate that the body is encoded by passing encoded=true in the URL parameters. Be sure to use strict Base 64 encoding, which encodes new line (\n) characters.

Alternatively, if your file is available at a public URL, you can pass an attachment_url parameter instead of a request body and we will download the file for you. If it is not a public URL, we will not be able to access your file.

Use the document_tags[] parameter to categorize the document. It can be included multiple times to assign several tags to one document. The available stipulation tags are:

  • account_must_be_positive_before_funding

  • accounts_receivable_report_invoices

  • balance_sheet_income_statement

  • balance_sheet

  • bank_statement

  • confirm_current_or_past_funding

  • drivers_license

  • information_on_additional_owner

  • month_to_date

  • payback_months

  • proof_of_ownership

  • signed_contracts

  • tax_return

  • twelve_month_bank_verification

  • ucc_information

  • voided_check

You may omit document_tags[] if your document does not match any of the defined tags, or if you are unsure which tag to use.

Note: Avoid the other tag. Uploading an attachment with the other tag returns a “description cannot be blank” error, because there is not yet a way to submit a description through the API. No description is required for any of the tags listed above.

Example URI

POST /v1/submissions/lead_id/closing_attachment?filename=filename&document_tags[]=&document_tags[]=&encoded=encoded
URI Parameters
HideShow
lead_id
string (required) 

The ID received when you initially submitted your lead (the same id returned by the lead submission endpoint).

filename
string (required) 

The desired filename in our system for the attachment you are uploading, including the extension. For example “closing_package.pdf”.

document_tags
array[string] (optional) 

Tags used to categorize the document. This parameter can be included multiple times. You may omit it if your document does not match any of the defined tags, or if you are unsure which tag to use.

encoded
boolean (optional) 

Set to true if the request body is Base 64 encoded. Be sure to use strict Base 64 encoding, which encodes new line (\n) characters.

Request
HideShow
Headers
Content-Type: application/pdf
api_key: Your_API_KEY
Body
Binary of your file
Response  202
HideShow
Headers
Content-Type: application/json
Body
{
  "message": "Your attachment was received and is being processed"
}
Response  400
HideShow

You will receive a 400 Bad Request if a required field is missing or invalid, or the file could not be retrieved — for example, a missing or blank filename, a blank lead id, an empty request body, or an attachment_url we are unable to access. The message varies with the cause (for example URL is not permitted for a non-public URL, or Failed to download attachment).

Headers
Content-Type: application/json
Body
{
  "message": "You must provide a filename"
}
Response  413
HideShow

Attachments larger than 100MB are rejected.

Headers
Content-Type: application/json
Body
{
  "message": "Attachment Too Large"
}

Submit Multiple Attachments

POST/v1/attachments

This endpoint is for uploading multiple documents associated with your recently created lead.

Upload one or more documents to an existing lead, submission, or stip opportunity in a single request. Each attachment must be referenced by URL, S3 location, or base64-encoded data.

Notes:

  • Attachment Limit - 100MB

  • At least 1 attachment must be present. These is a max of 25 attachments

  • One and only one of (uuid, lead_id, stip_opportunity_uuid) must be present

Example URI

POST /v1/attachments
URI Parameters
HideShow
uuid
string (required) 

Submission UUID

lead_id
string (required) 

Encrypted lead ID returned by /v1/lead

stip_opportunity_uuid
string (required) 

stip_opportunity_uuid Stip opportunity UUID

attachments
array (required) 

At least one attachment object must be present

Request
HideShow
Headers
api_key: Your_API_KEY
Body
{
  "lead_id": "<encrypted-lead-id>",
  "attachments": [
    {
      "filename": "bank_statement_jan.pdf",
      "attachment_url": "https://example.com/files/bank_jan.pdf",
      "tags": [
        "bank_statement"
      ]
    },
    {
      "filename": "tax_return.pdf",
      "bucket": "partner-uploads",
      "key": "docs/tax_return.pdf",
      "tags": [
        "tax_return"
      ]
    },
    {
      "filename": "voided_check.png",
      "encoded": true,
      "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlE...",
      "tags": [
        "voided_check"
      ]
    }
  ]
}
Response  202
HideShow
Body
{
  "message": "All attachments were received and are being processed",
  "total": 3,
  "accepted": 3,
  "results": [
    {
      "filename": "bank_statement_jan.pdf",
      "status": "accepted"
    },
    {
      "filename": "bank_statement_feb.pdf",
      "status": "accepted"
    },
    {
      "filename": "signed_application.pdf",
      "status": "accepted"
    }
  ]
}
Response  207
HideShow
Body
{
  "message": "Some attachments could not be processed",
  "total": 3,
  "accepted": 2,
  "failed": 1,
  "results": [
    { "filename": "bank_statement_jan.pdf", "status": "accepted" },
    { "filename": "bank_statement_feb.pdf", "status": "accepted" },
    { "filename": "invalid_url.pdf", "status": "failed", "error": "Failed to
download attachment }
          ]
Response  400
HideShow
Body
Missing required fields, or attachments array is empty.
Response  413
HideShow
Body
The total request payload exceeded the size limit.

Retrieve the Status of an API Lead

GET/v1/deal_status/{lead_id}

After you’ve sucessfully submitted a Lead and its attachments you can use this endpoint to retrieve the status of that submission in our funding process.

The response fields will vary depending on the status of the given deal.

Deals in Processing will just have stage in the response.

Approved deals will have stage, max_approval, max_payments, offer_link, required_stipulations, notes, and offer_variants.

Declined deals will have stage, decline_drivers, and decline_notes.

If we are Missing Information needed to make a decision, the response will contain the stage and missing_info fields.

  • stage - the current state of your submitted deal in our process

  • max_approval - the maximum advance amount approved for this merchant

  • max_payments - the maximum number of payments approved for this merchant (term in days)

  • offer_link - link to our offer calculator where you can select terms and request contracts

  • decline_drivers - reasons why this deal was declined

  • decline_notes - additional explanation for why this deal was declined

  • missing_info - additional information that is needed for a decision to be made on this deal

  • required_stipulations - list of required documents or information necessary to review before funding. Each object in this list contains the key type that describes what kind of document is requested.

  • notes - external ISO notes

  • offer_variants - list of available offer types for this approved deal (e.g. base and buyout). Each offer variant object contains:

    • id - unique identifier
    • variant_type - offer type (e.g. base, buyout)
    • max_approval_amount - maximum approved advance amount
    • max_term - maximum term (in months)
    • max_term_buy_rate - maximum term buy rate
    • maximum_buyout_amount - maximum amount approved to go towards a buyout
    • net_funded_amount - total amount expected to be deposited into the customer’s account
    • position - Forward’s position
    • existing_financing_companies_to_buyout - financing companies paid off as a part of a buyout
    • required_stipulations - list of required documents or information necessary to review before funding. Each object in this list contains the key type that describes what kind of document is requested.

Example URI

GET /v1/deal_status/lead_id
URI Parameters
HideShow
lead_id
string (required) 

which of your previously submitted leads the attachment is associated with. The lead id can be found in the response to the leads endpoint.

Request
HideShow
Headers
api_key: Your_API_KEY
Response  200
HideShow
Body
{
  "stage": "Approval Sent",
  "max_approval": 30000,
  "max_payments": 7,
  "offer_link": "offer.com",
  "required_stipulations": [
    {
      "type": "Voided Check"
    }
  ],
  "notes": "Strong application with consistent revenue.",
  "offer_variants": [
    {
      "id": "variant-uuid-1",
      "variant_type": "base",
      "max_approval_amount": 30000,
      "max_term": 7,
      "max_term_buy_rate": 1.34,
      "maximum_buyout_amount": null,
      "existing_financing_companies_to_buyout": null,
      "position": 1,
      "net_funded_amount": 28500,
      "required_stipulations": [
        {
          "type": "Voided Check"
        }
      ]
    },
    {
      "id": "variant-uuid-2",
      "variant_type": "buyout",
      "max_approval_amount": 40000,
      "max_term": 9,
      "max_term_buy_rate": 1.38,
      "maximum_buyout_amount": 10000,
      "existing_financing_companies_to_buyout": [
        "Lender Co"
      ],
      "position": 2,
      "net_funded_amount": 19105,
      "required_stipulations": [
        {
          "type": "Voided Check"
        }
      ]
    }
  ]
}
Response  200
HideShow
Body
{
  "stage": "Declined",
  "decline_drivers": "Default history;Excessive liens or judgements",
  "decline_notes": "This merchant does not look credible"
}
Response  200
HideShow
Body
{
  "stage": "File Missing Info",
  "missing_info": "We're going to need more recent bank statements please!"
}
Response  200
HideShow
Body
{
  "stage": "Working"
}

Webhooks

Webhook Notifications

Whenever a deal reaches any of the stages given below, your callback endpoint will receive a POST Request notifying you of the lead_id and event_type that changed. This webhook leads to increased efficiency with real-time updates, along with limiting need to poll Forward Financing servers to get the status.

Stages which trigger webhook callback:

  • Approved

  • Declined

  • Waiting on ISO

Whenever this webhook callback is triggered, it is expected that your system will hit the deal status endpoint to gather more information about the event change.

POST Sample response

{ lead_id: lead id of the deal, event_type: event which caused this webhook callback }

Register Webhook URL

Resource

POST/v1/webhook

Webhooks allow your application to register callback endpoints which can listen for realtime updates to your deals.

Webhook URL provided must start with http:// or https://

Example URI

POST /v1/webhook
Request
HideShow
Headers
Content-Type: application/json
api_key: Your_API_KEY
Body
{
  "webhook_url": "https://yourwebsite.com/some-path"
}
Response  200
HideShow
Body
{
  "success": true
}
Response  422
HideShow
Body
{
  "errors": {
    "webhook_url": [
      "is not a valid URL"
    ]
  }
}

Resource

POST/v1/trigger_webhook

To be able to test your integration and callback response, we have added an endpoint which triggers the webhook.

Example URI

POST /v1/trigger_webhook
Request
HideShow
Headers
Content-Type: application/json
api_key: Your_API_KEY
Body
{
  "webhook_url": "https://yourwebsite.com/some-path",
  "lead_id": "Lead Id for the deal",
  "event_type": "Event for which you want to force webhook trigger"
}
Response  200
HideShow
Body
{
  "message": "Webhook trigger successful"
}
Response  400
HideShow
Body
{
  "message": "Please provide lead_id, webhook_url and event_type"
}

Generated by aglio on 11 Jun 2026