Portal API Docs (2025.10.09)

Download OpenAPI specification:Download

Run in Postman

Getting Started

The Portal API is a RESTful service. It uses resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.


PRODUCTION ACCESS

You will use our sandbox until your integration is reviewed and approved. Once approved we'll provide keys to use our production API at https://api.portal.io


SANDBOX ACCESS

STEP 1
Sign up for a free Sandbox Account at https://sandbox.portal.io. This is a dealer test account you will use to exchange test data.

STEP 2
After you have a sandbox account, let your Portal rep know, and they will provide you an API Application Key, as well as a Secret Key (used to hach the signature in your requests)

STEP 3
You're now ready to get your User Key. Please refer to the User Authentication section, which is next in these docs. The User Key is the last thing you'll need to start making requests to the sandbox API at https://sandbox.api.portal.io

User Authentication

To start making API calls you’ll need a User Key. You’ll make a request at https://sandbox.api.portal.io/authenticate/apikeyexchange.

Send your Portal account Username and Password and pass the following headers:

  • X-MSS-API-APPID - API Application Key
  • X-MSS-CUSTOM-DATE - a date time stamp of the request
  • X-MSS-SIGNATURE - A signature for the request.


SANDBOX SAMPLE SIGNATURE - GET a User Key

GEThttps://sandbox.api.portal.io/authenticate/apikeyexchangeMon, 29 Aug 2022 13:30:55 GMT

**Important** The signature must be hashed with HMAC SHA256 using Secret Key and converted to Base64





Once you have your User Key you are ready to start making requests. The signature format for all requests is as follows. Notice the UserKey is added to the end of the concatenated string.

[Verb of the Request][its URL][Content Type][Date Timestamp][User API key]


SANDBOX SAMPLE SIGNATURE - GET Proposal List

GEThttps://api.portal.io/proposalsMon, 29 Aug 2022 13:30:55 GMTGhr/FRUWkligku/RQC49bWl0PohT46mQaX0ptShYMvk=

Note, there is no content type for Get request.

**Important** The signature must be hashed with HMAC SHA256 using Secret Key and converted to Base64

Proposals

The 'Proposals' service contains two main endpoints: Search & Get Proposal List, and Get Proposal Details. The search endpoint provides you basic summary information about proposals, including the Proposal Id, which you can then use to query the Proposal details endpoint, and get full detail, including line items.

Search & Get Proposal List

Search & Get Proposal List

Request
query Parameters
SearchText
string

Search proposal by this text

Statuses
Array of strings
Items Enum: "Draft" "Submitted" "ViewedByClient" "Accepted" "Declined" "Delayed" "Completed" "EmailFailed" "Expired"
ContactId
integer <int32>
ModifiedAfter
string <date-time>

Modified after timestamp in UTC

SortBy
string
Enum: "CreatedDate" "ModifiedDate" "Number" "Name" "ClientName" "Status" "LastModifiedByMe"
IsArchive
boolean

If true return only archived proposals otherwise return non archive proposals

SortDirection
string
PageNumber
integer <int32>

Page number. Starting from 1

PageSize
integer <int32>

Page Size

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Proposal List.

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

get/public/proposals
Request samples
Response samples
application/json
{
  • "proposals": [
    ],
  • "proposalCount": 0
}

Get Proposal Details

Get Proposal Details

Request
path Parameters
ProposalId
required
integer <int32>

Proposal Id.

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Proposal Details

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

403

You do not have permission for this API call.

get/public/proposals/{ProposalId}
Request samples
Response samples
application/json
{
  • "id": 0,
  • "createdDate": "2019-08-24T14:15:22Z",
  • "clientLastDecisionDate": "2019-08-24T14:15:22Z",
  • "lastCompletedDate": "2019-08-24T14:15:22Z",
  • "lastModifiedDate": "2019-08-24T14:15:22Z",
  • "lastModifiedByUserDate": "2019-08-24T14:15:22Z",
  • "financialSummary": {
    },
  • "changeOrders": [
    ],
  • "number": 0,
  • "name": "string",
  • "status": "Draft",
  • "lastSubmittedDate": "2019-08-24T14:15:22Z",
  • "clientLastOpenedDate": "2019-08-24T14:15:22Z",
  • "customer": {
    },
  • "dealer": {
    },
  • "coverpageImageUrl": "string",
  • "aboutUs": "string",
  • "projectDescription": "string",
  • "areas": [
    ],
  • "profit": {
    },
  • "recurringServices": {
    },
  • "paymentSchedule": {
    },
  • "paymentRequests": [
    ],
  • "projectTerms": "string",
  • "lastModifiedUser": {
    }
}

Get Change Order Details

Get Change Order Details

Request
path Parameters
ProposalId
required
integer <int32>

Proposal Id.

ChangeOrderId
required
integer <int32>

Change Order Id.

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Change Order Details

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

403

You do not have permission for this API call.

get/public/proposals/{ProposalId}/changeorders/{ChangeOrderId}
Request samples
Response samples
application/json
{
  • "id": 0,
  • "createdDate": "2019-08-24T14:15:22Z",
  • "clientLastDecisionDate": "2019-08-24T14:15:22Z",
  • "lastCompletedDate": "2019-08-24T14:15:22Z",
  • "lastModifiedDate": "2019-08-24T14:15:22Z",
  • "lastModifiedByUserDate": "2019-08-24T14:15:22Z",
  • "financialSummary": {
    },
  • "number": 0,
  • "name": "string",
  • "status": "Draft",
  • "lastSubmittedDate": "2019-08-24T14:15:22Z",
  • "clientLastOpenedDate": "2019-08-24T14:15:22Z",
  • "customer": {
    },
  • "dealer": {
    },
  • "coverpageImageUrl": "string",
  • "aboutUs": "string",
  • "projectDescription": "string",
  • "areas": [
    ],
  • "profit": {
    },
  • "recurringServices": {
    },
  • "paymentSchedule": {
    },
  • "paymentRequests": [
    ],
  • "projectTerms": "string",
  • "lastModifiedUser": {
    }
}

Get Change Order List for the Given Proposal

Get Change Order List for the Given Proposal

Request
path Parameters
ProposalId
required
integer <int32>

Proposal Id.

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Change Order List by Proposal.

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

get/public/proposals/{ProposalId}/changeorders
Request samples
Response samples
application/json
[
  • {
    }
]

People

The People service allows you to manage a dealer’s contacts, which are used in proposals.

Search & Get Contact List

Search & Get Contact List

Request
query Parameters
SearchText
string

Search text

ContactTypes
Array of strings

Contact Types.

Items Enum: "Person" "Company"
SortBy
string
Enum: "ModifiedDate" "CreatedDate" "FirstName" "LastName"
SortDirection
string
PageNumber
integer <int32>

Page number. Starting from 1

PageSize
integer <int32>

Page Size

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Contact List.

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

get/public/people
Request samples
Response samples
application/json
{
  • "people": [
    ],
  • "peopleCount": 0
}

Create a New Contact

Create a New Contact

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Request Body schema: application/json
required
PartyType
string
Enum: "Person" "Company"
ContactType
string
Enum: "Client" "Employee" "Contractor" "Other"
FirstName
required
string

First Name (Maximum character length is 100)

LastName
string

Last Name (Maximum character length is 50)

CompanyName
string

Company Name (Maximum character length is 100)

ContactEmail
string

Email (Maximum character length is 256)

ContactEmailCC
string

Additioanl email(s) copied when a proposal is submitted

ContactPhone
string

Contact Phone (Maximum character length is 30)

Notes
string
Responses
200

Success

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

post/public/people
Request samples
application/json
{
  • "PartyType": "Person",
  • "ContactType": "Client",
  • "FirstName": "string",
  • "LastName": "string",
  • "CompanyName": "string",
  • "ContactEmail": "string",
  • "ContactEmailCC": "string",
  • "ContactPhone": "string",
  • "Notes": "string"
}
Response samples
application/json
{
  • "notes": "string",
  • "lastModifiedDate": "2019-08-24T14:15:22Z",
  • "primaryLocation": {
    },
  • "billingLocation": {
    },
  • "proposalCount": 0,
  • "paymentCount": 0,
  • "id": 0,
  • "partyType": "Person",
  • "contactCategory": "Undefined",
  • "firstName": "string",
  • "lastName": "string",
  • "companyName": "string",
  • "contactEmail": "string",
  • "contactEmailCC": "string",
  • "contactPhone": "string"
}

Get Contact Details

Get Contact Details

Request
path Parameters
PersonId
required
integer <int32>

Person Id.

query Parameters
IncludeCounts
boolean
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Success

400

Person not found.

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

403

You do not have permission for this API call.

get/public/people/{PersonId}
Request samples
Response samples
application/json
{
  • "notes": "string",
  • "lastModifiedDate": "2019-08-24T14:15:22Z",
  • "primaryLocation": {
    },
  • "billingLocation": {
    },
  • "proposalCount": 0,
  • "paymentCount": 0,
  • "id": 0,
  • "partyType": "Person",
  • "contactCategory": "Undefined",
  • "firstName": "string",
  • "lastName": "string",
  • "companyName": "string",
  • "contactEmail": "string",
  • "contactEmailCC": "string",
  • "contactPhone": "string"
}

Get Contact Location List

Get Contact Location List

Request
path Parameters
ContactId
required
integer <int32>
query Parameters
PageNumber
integer <int32>
PageSize
integer <int32>
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Contact Location list

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

403

You do not have permission for this API call.

get/public/people/{ContactId}/location
Request samples
Response samples
application/json
{
  • "contactLocations": [
    ],
  • "locationCount": 0
}

Create New Contact Location

Create New Contact Location

Request
path Parameters
ContactId
required
integer <int32>
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Request Body schema: application/json
required
ContactFirstName
string

Contact First Name (Maximum character length is 50)

ContactLastName
string

Contact Last Name (Maximum character length is 50)

ContactPhoneNumber
string

Contact Phone Number (Maximum character length is 50)

ContactEmail
string

Contact Email (Maximum character length is 100)

Street
required
string

Street (Maximum character length is 100)

Suite
string

Suite (Maximum character length is 100)

City
string

City (Maximum character length is 50)

PostalCode
string

Postal Code (Maximum character length is 20)

State
string

State (Maximum character length is 256)

Country
string

Country (Maximum character length is 256)

IsPrimary
boolean
IsBilling
boolean
Responses
200

Contact Location

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

404

This person does not exists.

post/public/people/{ContactId}/location
Request samples
application/json
{
  • "ContactFirstName": "string",
  • "ContactLastName": "string",
  • "ContactPhoneNumber": "string",
  • "ContactEmail": "string",
  • "Street": "string",
  • "Suite": "string",
  • "City": "string",
  • "PostalCode": "string",
  • "State": "string",
  • "Country": "string",
  • "IsPrimary": true,
  • "IsBilling": true
}
Response samples
application/json
{
  • "contactFirstName": "string",
  • "contactLastName": "string",
  • "contactPhoneNumber": "string",
  • "contactEmail": "string",
  • "isPrimary": true,
  • "isBilling": true,
  • "id": 0,
  • "street": "string",
  • "suite": "string",
  • "city": "string",
  • "postalCode": "string",
  • "state": "string",
  • "stateAbbrev": "string",
  • "country": "string",
  • "phone": "string"
}

Catalog

**These endpoints require separate authorization**

The Catalog service provides access to all items in the Portal catalog, including information about their MSRP, cost, sell prices and suppliers.

Search & Get Catalog Items

Search & Get Catalog Items

Request
query Parameters
SearchText
string
ParentCategoryId
integer <int32>
ParentCategoryIds
Array of integers <int32>
CategoryId
integer <int32>
CategoryIds
Array of integers <int32>
Brands
Array of strings
Suppliers
Array of strings
Industries
Array of integers <int32>
IsInStock
boolean
IsFavorite
boolean
IsAuthorized
boolean
IsDiscontinued
boolean
IsIndustrialFavorite
boolean
MinMsrp
number <double>

Filter for products with an MSRP (of the users current country currency. If it doesn't exist then USD MSRP is used.) greater than this amount.

MaxMsrp
number <double>

Filter for products with an MSRP (of the users current country currency. If it doesn't exist then USD MSRP is used.) less than this amount.

PageNumber
integer <int32>
PageSize
integer <int32>

Limit the number of results

IncludeImageUrl
boolean
ItemType
string
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

A catalog response

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

500

Internal error.

get/public/catalog
Request samples
Response samples
application/json
{
  • "items": [
    ],
  • "favoriteItems": [
    ],
  • "categoryFacets": [
    ],
  • "brandFacets": [
    ],
  • "supplierFacets": [
    ],
  • "totalItemCount": 0,
  • "processingTimeMS": 0,
  • "favoriteItemCount": 0,
  • "labors": [
    ],
  • "customItems": [
    ]
}

Category List

Return the current category structure.

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

A catalog response

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

500

Internal error.

get/public/catalog/categories
Request samples
Response samples
application/json
[
  • {
    }
]

Get Catalog Item Details

Get Catalog Item Details

Request
path Parameters
ItemId
required
integer <int32>

Item Id

query Parameters
ExtendedDetails
boolean

Provides additional details like full description, specs, linked resources

ItemType
string
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Product Details

204

The requested item doesn't exist

401

Not Authorized to access this endpoint or your HMAC hash was incorrect.

402

This action requires an active subscription.

403

You do not have permission for this API call.

get/public/catalog/{ItemId}
Request samples
Response samples
application/json
{
  • "description": "string",
  • "productUrl": "string",
  • "manufacturerProductUrl": "string",
  • "additionalImageUrls": [
    ],
  • "pdfResourceLinks": [
    ],
  • "videoResourceLinks": [
    ],
  • "specs": [
    ],
  • "suppliers": [
    ],
  • "id": 0,
  • "brand": "string",
  • "model": "string",
  • "shortDescription": "string",
  • "primaryImageUrl": "string",
  • "parentCategoryId": 0,
  • "categoryId": 0,
  • "categories": [
    ],
  • "isFavorite": true,
  • "isDiscontinued": true,
  • "msrp": {
    },
  • "defaultCost": {
    },
  • "sellPrice": {
    }
}

Zapier Triggers

Zapier triggers on the following events in Portal

  1. Proposal Status Change
  2. Person modification
  3. Order Status Change
  4. Payment Status Change

Zapier Trigger on Person Modification

Zapier Trigger on Person Modification

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
Responses
200

Person Item.

get/zapier/trigger/person
Request samples
Response samples
application/json
{
  • "location": {
    },
  • "id": 0,
  • "partyType": "Person",
  • "contactType": "Client",
  • "firstName": "string",
  • "lastName": "string",
  • "companyName": "string",
  • "contactEmail": "string",
  • "contactEmailCC": "string",
  • "contactPhone": "string"
}

Zapier Trigger for payment Status Change

Zapier Trigger for payment Status Change

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
Responses
200

Payment Item.

get/zapier/trigger/payment
Request samples
Response samples
application/json
{
  • "id": 0,
  • "description": "string",
  • "status": "string",
  • "amount": 0,
  • "createdDate": "2019-08-24T14:15:22Z",
  • "modifiedDate": "2019-08-24T14:15:22Z",
  • "dueDate": "2019-08-24T14:15:22Z",
  • "initiatedPaymentDate": "2019-08-24T14:15:22Z",
  • "paidDate": "2019-08-24T14:15:22Z",
  • "clientName": "string",
  • "personId": 0,
  • "proposalId": 0,
  • "number": 0,
  • "paidVia": "string",
  • "isEstExpired": true,
  • "paymentProcessorType": "string",
  • "proposalPaymentScheduleItemId": 0
}

Zapier Trigger for Proposal Status Change

Zapier Trigger for Proposal Status Change

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
Responses
200

Proposal List.

get/zapier/trigger/proposal
Request samples
Response samples
application/json
{
  • "number": 0,
  • "status": "string",
  • "total": 0,
  • "customer": {
    },
  • "proposalPdf": "string",
  • "proposalCsv": "string",
  • "installerPdf": "string",
  • "salesPerson": "string",
  • "salesPersonEmail": "string",
  • "areas": [
    ],
  • "financialSummary": {
    },
  • "profit": {
    },
  • "recurringServices": {
    },
  • "changeOrders": [
    ],
  • "id": 0,
  • "name": "string"
}

Zapier Trigger for Order Status Change

Zapier Trigger for Order Status Change

Request
header Parameters
Accept
required
string

Accept Header

Value: "application/json"
Responses
200

Order Item

get/zapier/trigger/order
Request samples
Response samples
application/json
{
  • "number": 0,
  • "createdDate": "2019-08-24T14:15:22Z",
  • "modifiedDate": "2019-08-24T14:15:22Z",
  • "status": "string",
  • "total": 0,
  • "partCount": 0,
  • "orderSuppliers": [
    ],
  • "id": 0,
  • "name": "string"
}

Authentication

Authenticate User & Get User Token

Sign In

Request
query Parameters
UserName
required
string <= 256 characters

user email address

Password
required
string <password>

user password

header Parameters
Accept
required
string

Accept Header

Value: "application/json"
X-MSS-API-APPID
required
string

Application Id

X-MSS-CUSTOM-DATE
required
string

A date timestamp of the request

X-MSS-SIGNATURE
required
string

A signature for the request

X-MSS-API-USERKEY
required
string

User API Key

Responses
200

Success

401

Invalid credentials or User Email is not verified

get/authenticate/apikeyexchange
Request samples
Response samples
application/json
{
  • "userId": "string",
  • "sessionId": "string",
  • "userName": "string",
  • "displayName": "string",
  • "referrerUrl": "string",
  • "bearerToken": "string",
  • "refreshToken": "string",
  • "refreshTokenExpiry": "2019-08-24T14:15:22Z",
  • "profileUrl": "string",
  • "roles": [
    ],
  • "permissions": [
    ],
  • "authProvider": "string",
  • "responseStatus": {
    },
  • "meta": {
    }
}