facebook pixel

Creating leads using the API


In this guide

1. Goals of this guide

While we try to make Pylon the best platform it can be to help you run your solar business, there are plenty of things it can't or won't do. This is where integrations come in—you can plug Pylon into the other systems you use. Doing this reduces errors from manual data entry, saves time, helps you respond to opportunities faster, and frees your staff to focus on more important things.

This guide will walk you through the process of using our CRM API in order to send details about potential sales into your Pylon account. This guide is intended for a technical audience—in particular, you should be comfortable with how to use HTTP APIs and JSON. Examples are given in JavaScript.

If that isn't you, you may want to send this guide to your IT team or website contractor.

2. Leads and opportunities in Pylon

In Pylon, leads and opportunities are critical objects you will work with as part of customer relationship management (CRM).

A lead represents a relationship between your business and an external entity. In the case of residential solar businesses, that "external entity" will usually be a homeowner or family. When you're selling commercial solar, that entity may be another business.

An opportunity is a chance to earn revenue. For solar businesses, each opportunity is usually a single solar project. But you may have other kinds of opportunities, too—installing other types of equipment, performing post-sale servicing, or even selling other services that aren't solar-related if your business does that.

People are represented in the system as contacts.

Facts about leads and opportunities

  • One lead relationship can have many sales opportunities.
  • Leads and opportunities both have a primary contact, but may also include other non-primary contacts.
  • Leads contain all the conversation you have as part of that relationship (emails, SMSs, call logs, etc.).
  • Opportunities contain value, as well as details about solar installation.
  • Leads have statuses, but they don't move through a pipeline—your relationship carries on even after a deal is done or a system is sold.
  • Opportunities move through stages of a pipeline and are eventually closed when the deal is done.

3. Using the API

Before we dive into sending leads to the API, make sure you are set up to make API requests. Make sure you have created an API token in your API settings and are ready to use it.

The examples in this guide use JavaScript and will run in your browser, or in NodeJS if you enable a fetch polyfill. Our full API documentation contains examples using curl.

4. Create a lead and opportunity

Leads, opportunities and contacts are all separate resources in the CRM system and API. However, for convenience when integrating with a source of leads, we have created a "form" endpoint which accepts data and creates all three entities in a single request. Here is an example of the body of a request to this API:

{
  "contact": {
    "first_name": "Damien",
    "last_name": "Lewis",
    "phone_number": "0400 000 111"
  },
  "lead": {
    "source_type": "doorknock"
  },
  "opportunity": {
    "title": "Damien's beach house",
    "notes": "Call to discuss options for premium brands"
  }
}

Note that this request does not follow the JSON:API format like most of our API endpoints; this endpoint is intended to serve a specific use-case and is not part of a single resource's CRUD API.

Each section of the request will be used to create the corresponding object in the backend. Note that a lead and contact will always be created, but if you pass no "opportunity" data, then an opportunity will not be created. Salespeople can create the opportunity manually when following up with the lead.

This is the JavaScript code to send this request to the leads API:

let apiToken = "your api token";
let apiBaseUrl = "https://api.getpylon.com/v1";

let requestBody = {
  contact: {
    first_name: "Damien",
    last_name: "Lewis",
    phone_number: "0400 000 111",
  },
  lead: {
    source_type: "doorknock",
  },
  opportunity: {
    title: "Damien's beach house",
    notes: "Call to discuss options for premium brands",
    custom_property_values: {
      wants_battery: true,
    },
  },
};

let promisedResponse = fetch(apiBaseUrl + "/lead_form", {
  method: "post",
  credentials: "include",
  headers: {
    Authorization: "Bearer " + apiToken,
    "Content-Type": "application/json",
    Accept: "application/vnd.api+json",
  },
  body: JSON.stringify(requestBody),
});

promisedResponse
  .then((response) => response.json())
  .then((json) => console.log(json));

For more detailed information about the leads API, including providing custom property values to match your own data sources and sales process, visit our full documentation page:

We have used the source_type of doorknock in this example script. We recommend choosing a small set of unique and specific names to represent your lead sources. They will help you analyse the effectiveness of your different sales efforts.

What is most important is that the source_type gives adequate context for the source_id, if provided, to be understood. If the lead came from a third-party provider like SolarQuotes or SolarChoice, we recommend using the domain name of that provider. If the lead came from your own website, we recommend using the domain of your website, with a path if you have different forms. If the API is being used by, for example, a CRM integration, we recommend identifying the CRM, or passing on whatever information it has about the lead's source.

View leads API documentation

5. Legacy CRM integration

While our CRM rebuild is in progress, the new leads API can still be used to send leads to our existing CRM software as well. If you integrate in this way, you won't have to change your integration when you begin using the new CRM.

In order for leads created through the API to appear as opportunities in the legacy CRM system, you need to ask us to enable this integration, and then modify the request in the above example slightly. Here's the modified script. Note the new Prefer header in this request, as well as the new custom properties in the request body:

// ...

let requestBody = {
  contact: {
    first_name: "Damien",
    last_name: "Lewis",
    phone_number: "0400 000 111",
  },
  lead: {
    source_type: "doorknock",
  },
  opportunity: {
    title: "Damien's beach house",
    notes: "Call to discuss options for premium brands",
    custom_property_values: {
      wants_battery: true,
      // You may provide any of the following custom properties which are specific to Pylon CRM:
      "getpylon.com:status_name": "New",
      "getpylon.com:address_single_line": "42 Wallaby Way, Sydney",
      "getpylon.com:label_names": ["celebrity", "another-label"],
      "getpylon.com:source_rejection_link":
        "https://solarleads.com.au/leads/12345/reject",
    },
  },
};

let promisedResponse = fetch(apiBaseUrl + "/lead_form", {
  method: "post",
  credentials: "include",
  headers: {
    Authorization: "Bearer " + apiToken,
    "Content-Type": "application/json",
    Accept: "application/vnd.api+json",
    // Add this header:
    Prefer: "pylon-legacy-crm=sync",
  },
  body: JSON.stringify(requestBody),
});

// ...

The Prefer header tells the API that we wish for the lead to be copied to the legacy account as well as remaining in the new system. If the sync fails for some reason, the lead will continue to exist in the new system, and the error will be recorded.

Several of the custom properties in the example above begin with a getpylon.com: prefix. This format is necessary for our system to understand the intended use of these specific properties. They will be passed into the Pylon CRM and become properties of the opportunity there.

Custom properties that do not have the getpylon.com: prefix will be added to the opportunity's notes. Read more about custom properties in the custom properties documentation.