© Pylon 2020

Introduction

The Pylon API is organized according to REST principles. We use resource-oriented URLs, content negotiation, hypermedia, and informative status codes and headers. Most endpoints accept and return JSON-encoded bodies, though other content types are sometimes available.

The API will evolve over time, but breaking changes will be kept to a minimum and made in consultation with our users.

Not a developer?

Send this page to your IT team or web development contractor. Or check out our Zapier integration (coming soon) to start integrating without needing to write code.


Authentication

To start making requests to the API, you'll need to first create an API token in your API settings area. You can create multiple tokens, and revoke them at any time. Tokens are associated with your team and the user who created them.

Pass your API token in the Authorization header as shown in the example, where $TOKEN should be replaced with your actual secret API token value. You should always use HTTPS when making requests containing sensitive information, and our API will return an error if you use a non-HTTPS URL.

API token security

Your API token is intended for server-side use, and should not be distributed to browsers (e.g. in page HTML or in a JavaScript bundle), nor committed to source control. If you suspect a token has been compromised, revoke it immediately from your API settings.

Do not distribute API tokens using emails, SMS messages, or group chat software. Doing this leaves your API token in history from where it could be leaked. If you need to transmit API tokens between team members or to third parties (e.g. your IT contractor), use a secure ephemeral service. This instance of SnapPass provides such a service.

Delete unused API keys, and keys created for development or testing purposes, to reduce the chance of a leak. Consider regenerating API keys periodically by creating a new key, switching your applications to it, then deleting the old key. Our API logging helps you ensure that you have switched completely before deleting the old key.

Permissions

When you create an API token to make requests with, you can assign it permissions. By creating multiple tokens with appropriate permissions, you can increase the security of your integration.

Permission Description
read This is implicitly allowed for all API tokens.
write This is required in order to create or update any resources.
payment This permission is required for any billable API calls, as well as API calls which may spend your Pylon Observer credit balance.
admin Certain parts of the API contain more sensitive company information, and to read or write these resources, this additional permission is required.

REST Resources

Our API follows a subset of the JSON:API specification. As such, there are several predictable ways all endpoints will behave. Developers are encouraged to use JSON:API-compatible tools and libraries when working with our API.

Content types

When making requests to resource endpoints, your client should specify the Accept: application/vnd.api+json request header. In addition, requests with bodies (e.g. POST, PATCH) should include the header Content-Type: application/vnd.api+json.

All API endpoints which represent resources will respond with the header Content-Type: application/vnd.api+json.

The response content-type has one parameter, ext="https://api.getpylon.com/jsonapi" which describes our extensions to the spec (see below).

Single resources

A response body representing a single resource will contain a data property which is an object containing the resource. All resources contain type, id, attributes and relationships, and usually contain links.

Collection resources

A response body representing a collection of resources will contain a data property which is an array of resource objects. Each object in the array is identical to the individual resource object described above.

See the example belowto the right for an illustration of a typical response body.

Filtering response fields

If you want to reduce the size of response bodies from the API—for example, if you are only interested in one field, not the rest of the response—you may use JSON:API sparse fieldsets to filter response bodies. The general format is to provide a query parameter fields[type]=field1,field2 where the type is the type of an object included in the response body, and field1 and field1 are names of either attributes or relationships of the object.

For example, here is URL for a request to the users API which filters the response fields.

https://api.getpylon.com/v1/users?fields[users]=email

In the response to this request, all objects of the users type will only contain an email attribute, and no relationships:

Pagination

A response body representing a collection will have pagination links in a top-level links property. It will contain information about the entire collection (e.g. its total size) in a top-level meta property. You should not construct paginated URLs manually! Use the links!


Billing

Some methods in the API may incur billing charges when used. These methods are marked with a label under their title:

Billable

In order to make billable requests, your API token must be given the payment permission when it is created. This prevents you from accidentally causing billing with API tokens meant for administrative purposes.


Errors

Our API uses HTTP status codes and responses in the problem details format to indicate failures. See documentation for specific error types.

Common status codes

Our API makes use of HTTP response codes to indicate the success or failure of requests. Codes in the 200-299 range represent successes. Codes in the 400-599 range represent errors. Described below are the most common response codes you will encounter.

200

Success. Response body will contain a resource representation.

201

Success. A new resource was created and its representation is included in the response.

204

Success. Response body will be empty.

400

There was a problem with the syntax of your request (e.g., invalid JSON formatting).

401

You did not provide sufficient or correct authentication information.

402

When performing an operation that requires payment, this failure indicates your account has insufficient credit to complete it.

403

You are not permitted to perform the action. For example, maybe the API token being used has only the read permission and you attempted a write. Missing payments permissions will cause 403 errors, not 402 errors.

406

The request used content negotiation incorrectly. This is typically because the request did not specify the Accept: application/vnd.api+json header.

415

The request body content type was not accepted. This is typically because the request did not specify the Content-Type: application/vnd.api+json header.

422

Validation failure. Some properties of the request failed validation. More detail will be provided in the errors property, as in the example response belowto the right.


Users

Each of your employees should each have a unique account they can log in to Pylon with. Sharing accounts means you will have less accurate control over your employees' access to the software, and less accurate metrics on their usage. Each of these accounts is a User.

The user object

Attributes

full_name
string

email
string

gravatar_url
string

URL of the Gravatar associated with this user's email address.

photo_url
string

URL of the user's uploaded profile image.

created_at
string
Format: date-time

updated_at
string
Format: date-time


Users › List users read

This resource lists all users in the team your API token belongs to. This is useful for combining with other resources in this API to get details about users which are referenced by their ID. You can then choose to display details such as their name, email, and profile picture.

Returns

A collection of user objects

Users › Show user read

Returns

An instance of the user object

User reporting Preview

This API is in preview and breaking changes may be made without warning.

This API allows you to get statistics about your users' activity in Pylon. Each call to the API can return information about multiple users. The response contains data that is formatted so it is easy to produce charts or tables from.

User reporting › View report read

Currently, in order to make a request to this API, the user_ids query parameter must be a non-empty list. You can find suitable user IDs by calling the list users endpoint.

Available metrics

solar_projects.created
The number of solar projects created.
solar_projects.sold
The number of solar projects marked as sold.
solar_projects.esignature_request_sent
The number of projects for which E-signature requests were sent to customers.
credit_spends.products
The different products that users spent credits on. This includes, e.g., creating projects, unlocking Pro, and sending esignature requests.

Query parameters

start_date
string
Format: date

Start of date range to query in the format YYYY-MM-DD.

end_date
string
Format: date

End of date range to query in the format YYYY-MM-DD.

timezone_name
string

The timezone the above dates are in. For example, Australia/Sydney.

metric_name
string

One of the metrics described above.

user_ids
string

List of user IDs to fetch metrics for separated by commas.

Returns

data
object

data.metric
string

The metric that is being queried

data.chart_data
object

This schema represents data that should be displayed as a chart. It's based on Chart.js's data format, with some changes to make it slightly more generic and. It doesn't pretend to specify an entire chart. For example, this schema doesn't specify whether to display the chart as bars, lines, etc. It needs to be combined with a little knowledge from the client in order to create the final presentation.

data.chart_data.domain_labels
optional array of strings

The domain is the "independent" axis of the chart, usually the X axis. If present, domain_labels must have the same length as all series values arrays.

data.chart_data.domain_labels[*]
string

data.chart_data.range_labels
optional array of strings

The range labels would typically go up the Y axis. This property is not always used, because some charts (e.g. pie charts) won't display an axis for the range.

data.chart_data.range_labels[*]
string

data.chart_data.series
array of objects

The series array contains all the actual data serieses.

data.chart_data.series[*].id
string

Identifier not intended for human consumption.

data.chart_data.series[*].label
optional string

Label of the series. Should be human-readable.

data.chart_data.series[*].values
array

Data values. The values of this array may have any type.


Solar projects

Each solar project is located at one address and represents plans to install a single solar system. This might involve multiple solar arrays, but typically all behind the same meter.

The solar_projects resource represents the project itself, including location and customer details. Each project may have more than one design, as you go through the process of determining the best system to fit your customer's needs. For more details about the solar designs proposed for each project, see the solar designs resource.

The solar project object

Attributes

reference_number
string

This reference number can be used to identify the project in external systems

site_location
array of numbers

[Longutide, latitude] coordinates of this project.

site_location[*]
number

site_address
object

Street address of this project. Note that users can edit some of these properties to make cosmetic corrections.

customer_details
object

Information about the customer which will be displayed in web proposals for this project.

is_archived
boolean

Has this project been archived?

created_at
string
Format: date-time

updated_at
string
Format: date-time

Relationships

owner

A single user

designs

A collection of solar designs


Solar projects › List solar projects read

Projects are returned in the order they were created, least recent first. Results include archived projects.

Query parameters

filter
optional object

filter[is_archived]
optional string

Whether to list projects that have been archived. Defaults to false.

Allowed values: "true" "false" "any"

filter[reference_number]
optional string

Return only the project with this reference number, if any.

filter[created_at.gte]
optional string
Format: date-time

List projects created on or after the given timestamp.

filter[created_at.lt]
optional string
Format: date-time

List projects created before the given timestamp.

filter[owner]
optional string

Only projects owned by the user with this id. May be a comma-separated list to include multiple owners.

fields
optional object

fields[solar_projects]
optional string

Limit the fields returned for these projects.

fields[solar_designs]
optional string

These fields will be applied to links to solar design resources from this result.

Returns

A collection of solar project objects

Solar projects › Show solar project read

Query parameters

fields
optional object

fields[solar_projects]
optional string

Limit the fields returned for these projects.

fields[solar_designs]
optional string

These fields will be applied to links to solar design resources from this result.

Returns

An instance of the solar project object

Solar designs Preview

This API is in preview and breaking changes may be made without warning.

While this API is still in preview, you may wish to use the legacy solar projects API. That API will continue working for the forseeable future.

Each solar design contains a wealth of information about the layout, connection, configuration and pricing of a solar system. We are planning to expose much of this information via the API, but until we decide on the best way to do this, only basic information is available.

The solar design object

Attributes

summary
object

The summary contains high-level information about this design.

summary.dc_output_kw
number

Rated DC output size of the system in kilowatts.

summary.storage_kwh
number

Total storage capacity included in this design, in kilowatt-hours.

summary.web_proposal_url
string

URL of the web proposal associated with this design. This page is accessible without authentication and contains the customer's sensitive information like name and address, so share this URL with care.

summary.latest_snapshot_url
string

URL of the image showing the latest panel snapshot of this design.

locale
object

Contains data specific to different countries, keyed under the country's two-letter ISO code.

pricing
object

Contains data about the pricing inputs for this design.

pricing.total
number

The total cash price (in cents) charged for this design.

pricing.total_includes_tax
boolean

Does the total include any taxes?

pricing.currency
string

The currency all amounts for this design are expressed in. Amounts are expressed in whole numbers of cents, so an amount of 10000 would, in dollars, equate to $100.00.

module_types
array of objects

The different kinds of solar module used in this design. Usually there will only be one type.

module_types[*].sku
string

A unique identifier of this hardware. See solar modules for more info.

module_types[*].description
string

A human-readable label for this type of panel. Do not attempt to parse meaningful information from this string; if you need more detail, look up the datasheet using the sku.

module_types[*].quantity
integer

The number of this type of module used in the design

module_types[*].type_url
string

A permalink to this module type's definition

inverter_types
array of objects

The different kinds of inverter used in this design. Usually there will only be one type.

Relationships

project

A single solar project


Solar designs › List solar designs read

Note that the filter query parameter fields[solar_designs] is mandatory when making requests to this resource. This is a slight divergence from the JSON:API spec and from other resources in our API. Read more about fields

Here's an example of a request URL that filters the response body to only include the summary and created_at fields:

https://api.getpylon.com/v1/solar_designs?fields[solar_designs]=summary,created_at

The fields you are allowed to include are the attributes and relationships of the solar design object. We require this in order to better track usage of different design properties without having to split the design into sub-resources.

Query parameters

filter
optional object

filter[project]
optional string

List designs belonging to the project with the given id

filter[created_at.gte]
optional string
Format: date-time

List designs created on or after the given timestamp.

filter[created_at.lt]
optional string
Format: date-time

List designs created before the given timestamp.

filter[dc_output_kw.gte]
optional number

List designs with a size at least this value.

filter[dc_output_kw.lt]
optional number

List designs with size less than this value.

fields
object

fields[solar_designs]
string

Comma-separated list of fields to include. E.g. created_at,summary

Returns

A collection of solar design objects

Solar designs › Show solar design read

Note that the filter query parameter fields[solar_designs] is mandatory when making requests to this resource. This is a slight divergence from the JSON:API spec and from other resources in our API. Read more about fields

Here's an example of a request URL that filters the response body to only include the summary and created_at fields:

https://api.getpylon.com/v1/solar_designs?fields[solar_designs]=summary,created_at

The fields you are allowed to include are the attributes and relationships of the solar design object. We require this in order to better track usage of different design properties without having to split the design into sub-resources.

Query parameters

fields
object

fields[solar_designs]
string

Comma-separated list of fields to include. E.g. created_at,summary

Returns

An instance of the solar design object

Solar modules Preview

This API is in preview and breaking changes may be made without warning.

This collection contains information about every solar module available in Observer. This data is sourced from the manufacuturer datasheets themselves, which we link to as part of the API response.

When building with Observer, feel free to use these datasheets to enhance your integration. We will expose more information as part of each datasheet in the future; subscribe to our developers mailing list to be kept up-to-date.

The solar module object

The id of a solar module datasheet is refered to as its SKU (stock keeping unit). These SKUs have been generated using a UUID v5 computed from the module's identity properties. You are encouraged to use these SKUs to uniquely identify solar modules in your own systems if you like.

Attributes

name
string

identity
object

identity.brand
string

Company/brand that produces this module.

identity.series
string

The line of module.

identity.model_number
string

The most specific product code this product has been assigned.

identity.sku_identifier
string

This helps create a unique SKU in cases where other properties are not unique enough.

files
object

files.datasheet_url
string

The URL of the manufacturer's datasheet for this component.


Solar modules › Show solar module read

Returns

An instance of the solar module object

Solar inverters Preview

This API is in preview and breaking changes may be made without warning.

This collection contains information about every solar inverter available in Observer. This data is sourced from the manufacuturer datasheets themselves, which we link to as part of the API response.

When building with Observer, feel free to use these datasheets to enhance your integration. We will expose more information as part of each datasheet in the future; subscribe to our developers mailing list to be kept up-to-date.

The solar inverter object

The id of a solar module datasheet is refered to as its SKU (stock keeping unit). These SKUs have been generated using a UUID v5 computed from the module's brand, series, and model_number. You are encouraged to use these SKUs to uniquely identify inverters in your own systems if you like.

Attributes

name
string

identity
object

identity.brand
string

Company/brand that produces this module.

identity.series
string

The line of inverter.

identity.model_number
string

The most specific product code this product has been assigned.

identity.sku_identifier
string

This helps create a unique SKU in cases where other properties are not unique enough.

files
object

files.datasheet_url
string

The URL of the manufacturer's datasheet for this component.


Solar inverters › Show solar inverter read

Returns

An instance of the solar inverter object

Solar batteries Preview

This API is in preview and breaking changes may be made without warning.

This collection contains information about every solar battery available in Observer. This data is sourced from the manufacuturer datasheets themselves, which we link to as part of the API response.

When building with Observer, feel free to use these datasheets to enhance your integration. We will expose more information as part of each datasheet in the future; subscribe to our developers mailing list to be kept up-to-date.

The solar battery object

The id of a solar battery is refered to as its SKU (stock keeping unit). These SKUs have been generated using a UUID v5 computed from the module's brand, manufacturer, and model_number. You are encouraged to use these SKUs to uniquely identify inverters in your own systems if you like.


Solar batteries › Show solar battery read

Returns

An instance of the solar battery object

Leads Preview

This API is in preview and breaking changes may be made without warning.

A lead represents a relationship between your company and some external entity—usually, a family or another business. Leads are a very important part of customer relationship management (CRM). The most important distinction to understand is that leads are relationships, and opportunities are chances to make revenue. There may be multiple sales opportunities within one relationship.

When creating leads via the API, we recommend using the create leads and opportunities endpoint. This allows you to create several related entities in a single request with a straightforward schema.

The lead object

A lead mainly serves as a central hub for many other objects in Pylon. It doesn't hold a lot of data itself.

Attributes

title
string

Short name to identify this lead in the application UI.

source
object

Information about where this lead originated from.

source.name
string

This is the origin the lead came from. If the lead is from a third-party provider, we recommend using the domain of that provider. Beyond that, you may choose your own source names.

source.linked_id
string

The ID of the lead within the source system. If unknown or not applicable, you may use null.


Leads › Create leads and opportunities read write

When integrating with our CRM via the API, it may be convenient to create several entities (a lead, contact and opportunity) with a single call. This allows you to quickly and easily integrate with your website or other custom sources of sales opportunities.

While the opportunity contains the most important data, it's actually possible to use this form in a way that does not create one. In cases where very little information about the potential sale is known, you may not wish to provide values for opportunity properties. In this case, the endpoint will only create a lead and a contact.

Note that this endpoint requires a JSON:API Accept header. A successful form request will return a HTTP 303 redirect to the location of the created lead. Note that most API clients will transparently redirect and return the response from the new location. The lead endpoint returns a useful Link header so that you can forward a client's browser to the in-app representation of the created lead if you wish.

Related guide: learn how to create leads with the Pylon API

Request body

contact
object

contact.first_name
string

The contact person's first name.

contact.last_name
optional string

The contact person's surname.

contact.title
optional string

The formal title of the contact person (e.g. "Mr.", "Mrs.").

contact.email_address
optional string

contact.phone_number
optional string

contact.street_address
optional object

Address belonging to this contact.

contact.street_address.line1
string

The house number, street name, etc.

contact.street_address.line2
optional string

Suite or unit number, etc.

contact.street_address.city
string

contact.street_address.state
string

contact.street_address.zip
string

contact.street_address.country
string

contact.street_address.intended_use
optional string

Allowed values: "home" "office" "mailing" "billing" null

lead
optional object

lead.title
optional string

Title of the new lead to create. If not given, a title will be created automatically.

lead.source_name
optional string

How was this lead discovered? If not given, "unknown" will be used

lead.source_linked_id
optional string

ID of the lead in its source system, for example a third party lead generation website.

opportunity
optional object

opportunity.title
optional string

Distinguish this opportunity from others belonging to the same lead.

opportunity.value
optional integer

Estimated value of the opportunity.

opportunity.project
optional string

uid of linked project

opportunity.notes
optional string

opportunity.source_name
optional string

How was this opportunity discovered? If not given, the value of lead.source_name will be used.

opportunity.source_linked_id
optional string

ID of this opportunity in its source system.

opportunity.custom_property_values
optional object

This object should contain all custom properties you've defined. You may pass in properties with names that you have not yet defined in your settings. See custom properties for more details.

Returns

A 303 redirect to the location of the newly-created lead.


Leads › List leads read

Query parameters

filter
optional object

filter[source.name]
optional string

List leads from the specified source.

filter[created_at.gte]
optional string
Format: date-time

List leads created on or after the given timestamp. This refers to their creation date in Pylon, not necessarily in the lead source's system.

filter[created_at.lt]
optional string
Format: date-time

List leads created before the given timestamp.

Returns

A collection of lead objects

Leads › Show lead read

Along with the body content, this response will return a Link header pointing to the in-app URL of the lead. Its in-app rel can be used to identify it. For example:

Link: <https://observer.getpylon.com/platform/leads/FMQq4TBC>; rel="in-app alternate"; type="text/html"

Returns

An instance of the lead object

Opportunities Preview

This API is in preview and breaking changes may be made without warning.

Opportunities are the most important entity in your sales process. An opportunity is a chance to earn revenue. Opportunities will store most of the data about your potential sales. They will move through your sales pipeline and when they close, you get paid.

The opportunity object

Attributes

title
string

Short name to identify this lead in the UI.

value
integer

The value (in cents) this opportunity is estimated to be worth.

source
object

Information about where this opportunity originated from.

source.name
string

If this opportunity comes from a third-party provider, we recommend using the domain of that provider. Beyond that, you may choose your own source names.

source.linked_id
string

The ID of the opportunity within the source system, if applicable.

custom_property_values
object

Custom properties can be added in your team settings. Opportunities are allowed to have data in this object not configured in settings; in the web UI, these 'unstructured' custom properties will be hidden by default.


Opportunities › List opportunities read

Query parameters

filter
optional object

filter[lead]
optional string

List opportunities belonging to the given lead(s). May be a comma-separated string of multiple IDs.

filter[pipeline_stage]
optional string

List opportunities belonging to the given pipeline_stage(s). May be a comma-separated string of multiple IDs.

filter[created_at.gte]
optional string
Format: date-time

List opportunities created on or after the given timestamp.

filter[created_at.lt]
optional string
Format: date-time

List opportunities created before the given timestamp.

Returns

A collection of opportunity objects

Opportunities › Show opportunity read

Along with the body content, this response will return a Link header pointing to the in-app URL of the opportunity. Its in-app rel can be used to identify it. For example:

Link: <https://observer.getpylon.com/platform/opportunities/qpZ72TFx>; rel="in-app alternate"; type="text/html"

Returns

An instance of the opportunity object

Custom properties

When creating an opportunity via the lead form, you may provide custom properties. These properties may be used by your own software integrations to store and process data that's meaningful to you.

You may choose how to name and structure your custom properties, but custom properties must adhere to the following restrictions:

  • Custom property values may not be arrays or objects, only primitive types (strings, numbers, booleans and null).

  • Custom properties beginning with getpylon.com: and pylon.solar: are reserved for internal use. See below.

Custom properties whose name is prefixed by a domain we control are reserved. This means we control their definitions, and may validate them in more strict ways than other custom properties that are defined by your organisation. We also prevent you from providing custom properties we have not defined.

For example, pylon.solar:address may be used as described below, but pylon.solar:something may not be, because it is not defined below. However, you may use the custom properties something or yourdomain.com:something, because these properties are not prefixed by one of our domains.

Reserved custom properties

pylon.solar:address
optional object

The full address of the opportunity. When using Pylon CRM for solar sales, each opportunity should correspond to one solar project. Therefore, this address should be where the solar project will be installed.

pylon.solar:address.line1
string

The house number, street name, etc.

pylon.solar:address.line2
string

Suite or unit number, etc.

pylon.solar:address.city
string

pylon.solar:address.state
string

pylon.solar:address.zip
string

pylon.solar:address.country
string

getpylon.com:status_name
optional string

Used with legacy CRM integration. Name of the status in Pylon CRM the opportunity should be assigned to.

getpylon.com:address_single_line
optional string

Used with legacy CRM integration. Address of the opportunity as a single string.

getpylon.com:label_names
optional array of strings

Used with legacy CRM integration. Nmaes of labels that should be attached to the created opportunity.

getpylon.com:label_names[*]
string

getpylon.com:source_rejection_link
optional string

Used with legacy CRM integration. Link where a salesperson can to go reject this lead from its provider.



Australian STCs

The Clean Energy Regulator website contains more information about STCs. This API allows you to calculate the amount of STCs that a given solar system will generate.

Australian STCs › Calculate STC quantity read

Query parameters

sgu_kind
string

Allowed values: "solar_deemed"

output_kw
number

The rated DC output of the installed system, in kW.

site_postcode
string

installation_year
integer

deeming_period
optional integer

Defaults to the number of years remaining in the STC scheme.

Returns

data
object

data.stcs
integer

The number of STCs this system will create.

data.zone
integer

The rating zone the given postcode is associated with.

data.zone_rating
integer

The rating value for the given zone.

data.deeming_period
integer

The actual number of years used for deeming calculations.


API Tokens

The Pylon API may be used to manage your API tokens. We recommend that only sophisticated clients make use of this feature, as a misbehaving script could cause unintended consequences for access to your account.

The API token object

Relationships

creator

A single user


API Tokens › List API tokens read admin

This shows all currently-usable API tokens associated with your current team.

Returns

A collection of API token objects

API Tokens › Show API token read admin

Returns

An instance of the API token object

API Tokens › Revoke API token read write admin

Destroying an API token in this way will render it unable to make any further requests to the API. An API token may not destroy itself; attempting to do so will result in an error.

Returns

No content returned