External API Documentation

Integrate Your Systems with EasySolar API

API key–based integration grants You access to Calendar, Projects, Clients, and Components.
This gives you flexibility to integrate with your systems and automate processes.

External API Documentation

API key–based integration grants You access to Calendar, Projects, Clients, and Components. This gives you flexibility to integrate with your systems and automate processes.


Table of Contents

  1. Authentication
  2. Pagination
  3. Calendar API
  4. Projects API
  5. Clients API
  6. Components API
  7. Data Conventions
  8. Filtering Behavior
  9. Permission Model
  10. Error Handling
  11. Integration Patterns
  12. Stability & Versioning

1. Authentication

All requests must include an API key in the request header.

Authorization: Api-Key <raw_api_key>

Notes: - API keys are created and managed by company owners and admins. - Each key is scoped to specific resource permissions. - All requests are automatically scoped to the company attached to the API key.

Authentication Errors

StatusReason
401Missing or invalid API key
401Malformed authorization header
401Inactive API key
403Missing resource permission
402Company inactive

2. Pagination

List endpoints (Calendar, Projects, Clients) use limit/offset pagination.

Parameters

ParameterDescriptionDefaultMax
limitNumber of results to return100500
offsetPagination offset0

Response Envelope

{
  "count": 123,
  "next": null,
  "previous": null,
  "results": []
}

When next is null, you have reached the last page.


3. Calendar API

Represents scheduled events such as meetings, calls, and installations. Read-only.

Endpoints

GET https://api-production.easysolar-app.com/integrations/calendar/
GET https://api-production.easysolar-app.com/integrations/calendar/{id}/

Required permission: calendar_read

Response Example

{
  "id": "7d0f4d55-3b66-4c71-a86d-2b0ef2fca6d5",
  "category": "meeting",
  "subject": "Initial Site Visit",
  "description": "Discuss installation requirements and roof inspection.",
  "client": {
    "id": "4ab8e7cb-0a27-48f1-a0f6-6d6ecf5d8c6a",
    "name": "Solar Corp",
    "address": "Main Street 10, Warsaw",
    "phone": "+48123456789",
    "is_open": true
  },
  "participants": [
    {
      "first_name": "John",
      "last_name": "Smith",
      "email": "john.smith@example.com"
    }
  ],
  "start_at": "2026-06-15T09:00:00Z",
  "end_at": "2026-06-15T10:00:00Z",
  "full_day": false,
  "created_at": "2026-06-01T12:30:45Z"
}

Field Reference

FieldTypeDescription
idUUIDEvent identifier
categorystringEvent category (see values below)
subjectstringEvent title
descriptionstringAdditional event notes
clientobject | nullLinked client
participantsarrayEmployees assigned to the event
start_atdatetimeEvent start time (UTC)
end_atdatetimeEvent end time (UTC)
full_daybooleanWhether the event spans the entire day
created_atdatetimeEvent creation timestamp

Category Values

ValueDescription
meetingMeeting
callPhone call
installationInstallation appointment
contractContract signing
quotationQuotation presentation

Nested Objects

Client object:

FieldTypeDescription
idUUIDClient identifier
namestringClient name
addressstringClient address
phonestringClient phone number
is_openbooleanClient active status

Participant object:

FieldTypeDescription
first_namestringEmployee first name
last_namestringEmployee last name
emailstringEmployee email address

Filters

ParameterTypeDescription
start_at_afterdatetimeFilter events starting after this time
start_at_beforedatetimeFilter events starting before this time
end_at_afterdatetimeFilter events ending after this time
end_at_beforedatetimeFilter events ending before this time
categorystring (multi)Filter by category; repeat for multiple values
clientUUIDFilter by client ID

Example:

GET https://api-production.easysolar-app.com/integrations/calendar/?start_at_after=2026-01-01T00:00:00Z&category=meeting&category=call
Authorization: Api-Key <key>

4. Projects API

Represents client-related project records (e.g. solar installations). Read-only.

Endpoints

GET https://api-production.easysolar-app.com/integrations/projects/
GET https://api-production.easysolar-app.com/integrations/projects/{id}/

Required permission: projects_read

Response Example

{
  "id": "d8e22cb9-1d88-4a3d-a3fd-f954d1f23d59",
  "name": "Solar Installation - Warsaw Office",
  "address": "Aleje Jerozolimskie 120, Warsaw",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "client": {
    "id": "4ab8e7cb-0a27-48f1-a0f6-6d6ecf5d8c6a",
    "name": "Solar Corp",
    "address": "Main Street 10, Warsaw",
    "phone": "+48123456789",
    "is_open": true
  },
  "status": {
    "name": "In Progress",
    "order": 2
  },
  "currency": {
    "code": "PLN",
    "name": "Polish Złoty"
  },
  "total_price": "42500.00",
  "payback_period": 8,
  "created": "2026-05-01T09:00:00Z",
  "updated": "2026-06-01T15:30:00Z"
}

Field Reference

FieldTypeDescription
idUUIDProject identifier
namestringProject name
addressstringProject address
latitudedecimal | nullProject latitude
longitudedecimal | nullProject longitude
clientobjectLinked client (see Client object)
statusobjectProject status
currencyobjectCurrency used for financial values
total_pricedecimal stringCurrent project total price
payback_periodinteger | nullEstimated payback period in years
createddatetimeCreation timestamp
updateddatetimeLast update timestamp

total_price is returned as a decimal string to preserve precision. payback_period is null if not yet calculated. latitude/longitude are null if no location is set.

Nested Objects

Status object:

FieldTypeDescription
namestringStatus display name
orderintegerStatus ordering value

Currency object:

FieldTypeDescription
codestringISO currency code
namestringCurrency name

Filters

ParameterTypeDescription
created_afterdatetimeFilter by creation date (lower bound)
created_beforedatetimeFilter by creation date (upper bound)
updated_afterdatetimeFilter by update date (lower bound)
updated_beforedatetimeFilter by update date (upper bound)
clientUUIDFilter by client ID
statusUUIDFilter by status ID
namestringCase-insensitive partial name match

Example:

GET https://api-production.easysolar-app.com/integrations/projects/?client=<id>&name=solar
Authorization: Api-Key <key>

5. Clients API

Represents customer entities. Supports read and write operations.

Endpoints

GET    https://api-production.easysolar-app.com/integrations/clients/
POST   https://api-production.easysolar-app.com/integrations/clients/
GET    https://api-production.easysolar-app.com/integrations/clients/{id}/
PATCH  https://api-production.easysolar-app.com/integrations/clients/{id}/

Required permissions: clients_read (read), clients_write (write)

Response Example

{
  "id": "4ab8e7cb-0a27-48f1-a0f6-6d6ecf5d8c6a",
  "name": "Solar Corp",
  "description": "Commercial customer interested in a rooftop PV installation.",
  "address": "Main Street 10, Warsaw",
  "latitude": 52.2297,
  "longitude": 21.0122,
  "phone": "+48123456789",
  "is_open": true,
  "created": "2026-05-01T10:15:00Z",
  "updated": "2026-06-01T08:45:30Z"
}

Field Reference

FieldTypeDescription
idUUIDClient identifier
namestringClient name
descriptionstringAdditional notes
addressstringClient address
latitudedecimal | nullClient latitude
longitudedecimal | nullClient longitude
phonestring | nullClient phone number
is_openbooleanWhether the client is currently active
createddatetimeCreation timestamp
updateddatetimeLast update timestamp

Create Client

POST https://api-production.easysolar-app.com/integrations/clients/
{
  "name": "Client Name",
  "description": "Commercial customer",
  "address": "Address",
  "phone": "+48123456789",
  "latitude": 52.2297,
  "longitude": 21.0122
}

Update Client

PATCH https://api-production.easysolar-app.com/integrations/clients/{id}/

Only include the fields you want to update:

{
  "address": "New Address 15, Warsaw",
  "phone": "+48987654321"
}

Coordinate Rules

  • latitude and longitude must always be provided together.
  • Supplying only one coordinate results in a validation error.
  • If no location is set, both fields are returned as null.

Filters

ParameterTypeDescription
created_afterdatetimeFilter by creation date (lower bound)
created_beforedatetimeFilter by creation date (upper bound)
updated_afterdatetimeFilter by update date (lower bound)
updated_beforedatetimeFilter by update date (upper bound)
is_openbooleanFilter by active status (true or false)
namestringCase-insensitive partial name match
phonestringCase-insensitive partial phone match

6. Components API

Creates components for use in projects. Write-only.

Endpoint

POST https://api-production.easysolar-app.com/integrations/components/

Required permission: components_write

Component Types

Three component types are supported: panel, inverter, and other.


Panel

{
  "type": "panel",
  "manufacturer_name": "Longi",
  "name": "LR5-54HPH",
  "net_unit_price": "120.00",
  "nominal_power": "430.000",
  "length": "1.7220",
  "width": "1.1340",
  "weight": "21.500",
  "efficiency": "0.2100000",
  "short_circuit_current": "13.52000",
  "open_circuit_voltage": "37.85000",
  "current_temperature_coefficient": "0.045000",
  "voltage_temperature_coefficient": "-0.280000",
  "power_temperature_coefficient": "-0.350000"
}
FieldTypeRequiredDescription
typestringYesMust be "panel"
manufacturer_namestringYesManufacturer name
namestringYesPanel model name
net_unit_pricedecimalNoNet unit price
nominal_powerdecimalYesRated power (W)
lengthdecimalYesPanel length (m)
widthdecimalYesPanel width (m)
weightdecimal | nullNoWeight (kg)
efficiencydecimalYesConversion efficiency
short_circuit_currentdecimalYesShort-circuit current (A)
open_circuit_voltagedecimalYesOpen-circuit voltage (V)
current_temperature_coefficientdecimal | nullNoCurrent temperature coefficient
voltage_temperature_coefficientdecimal | nullNoVoltage temperature coefficient
power_temperature_coefficientdecimal | nullNoPower temperature coefficient

Inverter

{
  "type": "inverter",
  "manufacturer_name": "SMA",
  "name": "Sunny Tripower 5.0",
  "net_unit_price": "900.00",
  "nominal_power": "5000.000",
  "number_of_dc_inputs": 2
}
FieldTypeRequiredDescription
typestringYesMust be "inverter"
manufacturer_namestringYesManufacturer name
namestringYesInverter model name
net_unit_pricedecimalNoNet unit price
nominal_powerdecimalYesRated power (W)
number_of_dc_inputsintegerYesNumber of DC inputs

Other

{
  "type": "other",
  "name": "Mounting System",
  "unit": "pcs",
  "net_unit_price": "50.00"
}
FieldTypeRequiredDescription
typestringYesMust be "other"
namestringYesComponent name
unitstringNoUnit of measurement
net_unit_pricedecimalNoNet unit price

Response

{
  "id": "uuid",
  "type": "panel | inverter | other",
  "name": "string"
}

Notes

  • Manufacturers are automatically created if they don't exist.
  • Manufacturer uniqueness is scoped per company.
  • All panel-specific fields are validated before creation.

7. Data Conventions

IDs

All resource identifiers are UUID strings, stable and globally unique within a company:

"id": "550e8400-e29b-41d4-a716-446655440000"

Timestamps

All datetime fields are returned in ISO 8601 format, always in UTC:

"created": "2026-06-09T12:34:56Z"

Geolocation

Coordinates apply to Clients and Projects. They are stored as a geographic point and returned as separate fields:

"latitude": 52.2297,
"longitude": 21.0122

Null Handling

Fields that are not set are returned as null — they are never omitted from the response.


8. Filtering Behavior

General Rules

  • All filters are optional unless stated otherwise.
  • Multiple filters are combined with AND logic.
  • Multi-select filter values (e.g. category) use OR logic internally.
  • Invalid filter values return empty results or a validation error depending on field type.

Date Range Filters

Available across endpoints:

Filter fieldsBehavior
created_after / created_beforeRange filter on creation timestamp
updated_after / updated_beforeRange filter on last-update timestamp
start_at_after / start_at_beforeRange filter on event start time
end_at_after / end_at_beforeRange filter on event end time

Text Search Filters

Case-insensitive partial matching on name and phone:

?name=solar

Matches: "Solar Corp", "My Solar Project", etc.


9. Permission Model

API key permissions are configured independently per resource:

ResourceRead PermissionWrite Permission
Calendarcalendar_read(not supported)
Projectsprojects_read(not supported)
Clientsclients_readclients_write
Components(not supported)components_write

10. Error Handling

Error Format

General error:

{
  "detail": "Error message"
}

Field-level validation error:

{
  "field_name": ["Error message"]
}

Error Reference

StatusCategoryMeaning
401AuthenticationInvalid, missing, or inactive API key; malformed header
402BusinessCompany is inactive
403AuthorizationAPI key lacks the required resource permission
4xxValidationField-level errors returned as an object

Integration Checklist

If you encounter errors, verify:

  1. The API key has the correct resource permissions.
  2. The company account is active.
  3. All filter values (IDs, etc.) belong to the same company scope.

11. Integration Patterns

Sync Strategy

The recommended approach for syncing data:

  1. Fetch the list endpoint (paginated).
  2. Store the id as an external reference.
  3. Use the updated field for incremental syncs.

Pagination Handling

Iterate through pages by incrementing the offset until next is null:

GET https://api-production.easysolar-app.com/integrations/clients/?limit=100&offset=0
GET https://api-production.easysolar-app.com/integrations/clients/?limit=100&offset=100

Incremental Sync

Use date filters to fetch only records changed since your last sync:

GET https://api-production.easysolar-app.com/integrations/projects/?updated_after=2026-01-01T00:00:00Z

Filtering Best Practices

  • Prefer ID-based filters (client, status) over text searches for high-volume syncs.
  • Combine multiple filters to reduce result set size.
  • Avoid broad text searches on large datasets.

12. Stability & Versioning

Stable Guarantees

The following will not change without a versioned migration:

  • Endpoint URLs
  • Field names
  • UUID format
  • Pagination structure
  • Authentication scheme

Subject to Change (Non-Breaking)

  • Optional filters (new filters may be added)
  • Response enrichment (new fields may be added)

Versioning Policy

No explicit version is currently exposed in the URL. Breaking changes will introduce a new endpoint namespace:

https://api-production.easysolar-app.com/integrations/v2/...

Additive changes are considered non-breaking and may be deployed without a version bump.


End of Documentation

Contact us

Need help?

support@easysolar.app

Feel free to reach out and our dedicated team will respond to your inquiries promptly.

Sell ​​automatically with AI

Create an Automated AI Salesperson in 2 minutes

Add the AI photovoltaic proposals generator to your current website. Set your prices, choose your products, and customize your company’s branding. Your customers will receive an instant offer, and you’ll get an immediate email notification for every proposal and interested client.

Roof edge detection for solar panels