Customers

Listing all Customers

A GET request to /api/customers/ is used to list all customers.

Using count and offset restricts the number of returned customers.

Parameter Description
count Limit the number of results. This can improve performance.
offset The start position of results, used for paging result sets. Can be used with count parameter.
"""
List all customers using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customers_url = 'https://%s:%d/api/customers/?count=10&offset=0' % (ONSITE_HOST, ONSITE_PORT)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Setup a session for the http request.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False
session.stream = True

# Send the request to list all customers.
get_response = session.get(customers_url)
assert get_response.status_code == 200

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Get the response and print it.
response_xml = minidom.parseString(get_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<customers total_count="2">
   <customer id="15" uri="https://localhost:9630/api/customers/15/">
       <name>
           <first>Jane</first>
           <last>Smith</last>
       </name>
       <company/>
       <email/>
       <homepage/>
       <phone_numbers>
           <phone_number id="1">
               <main>true</main>
               <type>home</type>
               <list_order>1</list_order>
               <number>613-555-5555</number>
           </phone_number>
           <phone_number id="2">
               <main>false</main>
               <type/>
               <list_order>2</list_order>
               <number/>
           </phone_number>
           <phone_number id="3">
               <main>false</main>
               <type/>
               <list_order>3</list_order>
               <number/>
           </phone_number>
           <phone_number id="4">
               <main>false</main>
               <type/>
               <list_order>4</list_order>
               <number/>
           </phone_number>
       </phone_numbers>
       <photo/>
       <is_company>false</is_company>
   </customer>
   <customer id="3" uri="https://localhost:9630/api/customers/3/">
       <name>
           <first>Justine</first>
           <last>Trudel</last>
       </name>
       <company>Modeling Agency Ltd.</company>
       <email>[email protected]</email>
       <homepage>www.example.com</homepage>
       <phone_numbers>
           <phone_number id="1">
               <main>false</main>
               <type>work</type>
               <list_order>1</list_order>
               <number>123-456-7890</number>
           </phone_number>
           <phone_number id="2">
               <main>true</main>
               <type>mobile</type>
               <list_order>2</list_order>
               <number>098-765-4321</number>
           </phone_number>
           <phone_number id="3">
               <main>false</main>
               <type/>
               <list_order>3</list_order>
               <number/>
           </phone_number>
           <phone_number id="4">
               <main>false</main>
               <type/>
               <list_order>4</list_order>
               <number/>
           </phone_number>
       </phone_numbers>
       <photo/>
       <is_company>false</is_company>
   </customer>
</customers>

Warning

This request can time-out if there are too many customers to return. Use limit and offset parameters to mitigate this.

Note

It is recommended to search customers rather than to list them all. See Searching Customers.

Creating a Customer

A POST request to /api/customers/ is used to create a customers.

The following script creates a customer with the OnSite API.

There are other fields that can be set, however they can be left out if you don’t want to set them. Some fields will have default values set, depending on the setup in OnSite.

"""
Create a customer using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customers_url = 'https://%s:%d/api/customers/' % (ONSITE_HOST, ONSITE_PORT)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# This is the customer that will be created.
customer_xml = """
<customer>
    <name>
        <first>Jane</first>
        <last>Smith</last>
    </name>
    <phone_numbers>
        <phone_number id="1">
            <type>home</type>
            <number>613-555-5555</number>
        </phone_number>
    </phone_numbers>
</customer>
"""

# Create a session. This will persist cookies across all requests.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False

# Send the request to create the customer.
post_response = session.post(customers_url, data=customer_xml)
assert post_response.status_code == 201

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Get the response and print it.
response_xml = minidom.parseString(post_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<customer id="15" uri="https://localhost:9630/api/customers/15/">
    <name>
        <first>Jane</first>
        <last>Smith</last>
    </name>
    <company/>
    <email/>
    <homepage/>
    <phone_numbers>
        <phone_number id="1">
            <main>true</main>
            <type>home</type>
            <list_order>1</list_order>
            <number>613-555-5555</number>
        </phone_number>
        <phone_number id="2">
            <main>false</main>
            <type/>
            <list_order>2</list_order>
            <number/>
        </phone_number>
        <phone_number id="3">
            <main>false</main>
            <type/>
            <list_order>3</list_order>
            <number/>
        </phone_number>
        <phone_number id="4">
            <main>false</main>
            <type/>
            <list_order>4</list_order>
            <number/>
        </phone_number>
    </phone_numbers>
    <photo/>
    <is_company>false</is_company>
    <billing>
        <address>
            <address1/>
            <address2/>
            <city/>
            <state/>
            <country/>
            <zip/>
        </address>
    </billing>
    <shipping>
        <address>
            <address1/>
            <address2/>
            <city/>
            <state/>
            <country/>
            <zip/>
        </address>
    </shipping>
    <credit_hold>false</credit_hold>
    <new_import>false</new_import>
    <new_update>false</new_update>
    <birthday/>
    <credit_limit>0</credit_limit>
    <customer_id>C-15</customer_id>
    <credit_status uri="https://localhost:9630/api/customers/15/credit_status/"/>
    <ar_balance uri="https://localhost:9630/api/customers/15/ar_balance/"/>
    <import_id/>
    <account_status id="0" uri="https://localhost:9630/api/setup/account_statuses/0/">
        <name>None</name>
        <list_order>0</list_order>
    </account_status>
    <user/>
    <customer_category id="0" uri="https://localhost:9630/api/setup/customer_categories/0/">
        <name>None</name>
        <discount>
            <percent>0.000</percent>
        </discount>
        <pricing_level/>
    </customer_category>
    <customer_referredby id="0" uri="https://localhost:9630/api/setup/customer_referredbys/0/">
        <name>None</name>
    </customer_referredby>
    <currency id="0" uri="https://localhost:9630/api/setup/currencies/0/"/>
    <tax_code id="0" uri="https://localhost:9630/api/tax_codes/0/"/>
    <tax_exemption id="0" uri="https://localhost:9630/api/setup/tax_exemptions/0/"/>
    <terms id="0" uri="https://localhost:9630/api/setup/terms/0/"/>
    <language>
        <id>0</id>
        <language_name>English</language_name>
    </language>
    <merged_to>
        <customer/>
    </merged_to>
</customer>

Getting a Single Customer

A GET request to /api/customers/{id}/ is used to get a single customer.

"""
Get a product using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customer_id = 15
customer_url = 'https://%s:%d/api/customers/%d/' % (ONSITE_HOST, ONSITE_PORT, customer_id)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Setup a session for the http request.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False
session.stream = True

# Send the request to get a customer.
get_response = session.get(customer_url)
assert get_response.status_code == 200

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Get the response and print it.
response_xml = minidom.parseString(get_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<?xml version="1.0" ?>
<customer id="15" uri="https://localhost:9630/api/customers/15/">
   <created>2017-07-20T12:09:11.341236</created>
   <modified>2017-07-20T12:09:11.367859</modified>
   <name>
       <first>Jane</first>
       <last>Smith</last>
   </name>
   <company/>
   <email/>
   <homepage/>
   <phone_numbers>
       <phone_number id="1">
           <main>true</main>
           <type>home</type>
           <list_order>1</list_order>
           <number>613-555-5555</number>
       </phone_number>
       <phone_number id="2">
           <main>false</main>
           <type/>
           <list_order>2</list_order>
           <number/>
       </phone_number>
       <phone_number id="3">
           <main>false</main>
           <type/>
           <list_order>3</list_order>
           <number/>
       </phone_number>
       <phone_number id="4">
           <main>false</main>
           <type/>
           <list_order>4</list_order>
           <number/>
       </phone_number>
   </phone_numbers>
   <photo/>
   <is_company>false</is_company>
   <billing>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </billing>
   <shipping>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </shipping>
   <credit_hold>false</credit_hold>
   <new_import>false</new_import>
   <new_update>false</new_update>
   <birthday/>
   <credit_limit>0.00</credit_limit>
   <customer_id>C-15</customer_id>
   <credit_status uri="https://localhost:9630/api/customers/15/credit_status/"/>
   <ar_balance uri="https://localhost:9630/api/customers/15/ar_balance/"/>
   <import_id/>
   <account_status id="0" uri="https://localhost:9630/api/setup/account_statuses/0/">
       <name>None</name>
       <list_order>0</list_order>
   </account_status>
   <user/>
   <customer_category id="0" uri="https://localhost:9630/api/setup/customer_categories/0/">
       <name>None</name>
       <discount>
           <percent>0.000</percent>
       </discount>
       <pricing_level/>
   </customer_category>
   <customer_referredby id="0" uri="https://localhost:9630/api/setup/customer_referredbys/0/">
       <name>None</name>
   </customer_referredby>
   <currency id="0" uri="https://localhost:9630/api/setup/currencies/0/"/>
   <tax_code id="0" uri="https://localhost:9630/api/tax_codes/0/"/>
   <tax_exemption id="0" uri="https://localhost:9630/api/setup/tax_exemptions/0/"/>
   <terms id="0" uri="https://localhost:9630/api/setup/terms/0/"/>
   <language>
       <id>0</id>
       <language_name>English</language_name>
   </language>
   <merged_to>
       <customer/>
   </merged_to>
</customer>

Updating a Customer

A PUT request to /api/customers/{id}/ is used to change the details of a customer.

This must be preceded by a LOCK request to the same endpoint, and followed by an UNLOCK request. See Locking & Unlocking Resources.

"""
Update a customer using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customer_id = 15
customer_url = 'https://%s:%d/api/customers/%d/' % (ONSITE_HOST, ONSITE_PORT, customer_id)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# This is the updated information for the customer.
customer_xml = """
<customer>
    <email>[email protected]</email>
    <homepage>www.example.com</homepage>
</customer>
"""

# Create a session. This will persist cookies across all requests.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False

# Lock the customer before making the change.
lock_response = session.request('LOCK', customer_url)
assert lock_response.status_code == 200

# Send the request to update the customer.
put_response = session.put(customer_url, data=customer_xml)
assert put_response.status_code == 200

# Unlock the customer after the change is complete.
unlock_response = session.request('UNLOCK', customer_url)
assert unlock_response.status_code == 200

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Print the revised customer.
response_xml = minidom.parseString(put_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<?xml version="1.0" ?>
<customer id="15" uri="https://localhost:9630/api/customers/15/">
   <created>2017-07-20T12:09:11.341236</created>
   <modified>2017-07-20T13:46:22.552965</modified>
   <name>
       <first>Jane</first>
       <last>Smith</last>
   </name>
   <company/>
   <email>[email protected]</email>
   <homepage>www.example.com</homepage>
   <phone_numbers>
       <phone_number id="1">
           <main>true</main>
           <type>home</type>
           <list_order>1</list_order>
           <number>613-555-5555</number>
       </phone_number>
       <phone_number id="2">
           <main>false</main>
           <type/>
           <list_order>2</list_order>
           <number/>
       </phone_number>
       <phone_number id="3">
           <main>false</main>
           <type/>
           <list_order>3</list_order>
           <number/>
       </phone_number>
       <phone_number id="4">
           <main>false</main>
           <type/>
           <list_order>4</list_order>
           <number/>
       </phone_number>
   </phone_numbers>
   <photo/>
   <is_company>false</is_company>
   <billing>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </billing>
   <shipping>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </shipping>
   <credit_hold>false</credit_hold>
   <new_import>false</new_import>
   <new_update>false</new_update>
   <birthday/>
   <credit_limit>0.00</credit_limit>
   <customer_id>C-15</customer_id>
   <credit_status uri="https://localhost:9630/api/customers/15/credit_status/"/>
   <ar_balance uri="https://localhost:9630/api/customers/15/ar_balance/"/>
   <import_id/>
   <account_status id="0" uri="https://localhost:9630/api/setup/account_statuses/0/">
       <name>None</name>
       <list_order>0</list_order>
   </account_status>
   <user/>
   <customer_category id="0" uri="https://localhost:9630/api/setup/customer_categories/0/">
       <name>None</name>
       <discount>
           <percent>0.000</percent>
       </discount>
       <pricing_level/>
   </customer_category>
   <customer_referredby id="0" uri="https://localhost:9630/api/setup/customer_referredbys/0/">
       <name>None</name>
   </customer_referredby>
   <currency id="0" uri="https://localhost:9630/api/setup/currencies/0/"/>
   <tax_code id="0" uri="https://localhost:9630/api/tax_codes/0/"/>
   <tax_exemption id="0" uri="https://localhost:9630/api/setup/tax_exemptions/0/"/>
   <terms id="0" uri="https://localhost:9630/api/setup/terms/0/"/>
   <language>
       <id>0</id>
       <language_name>English</language_name>
   </language>
   <merged_to>
       <customer/>
   </merged_to>
</customer>

Adding a Customer Photo

A POST request to /api/customers/{id}/customer_photo/ is used to add a customer photo.

This must be preceded by a LOCK request to the same endpoint, and followed by an UNLOCK request. See Locking & Unlocking Resources.

"""
Add a customer photo using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

photo_file_path = '../images/sample-photo.jpg'
customer_id = 12
customer_url = 'https://%s:%d/api/customers/%d/' % (ONSITE_HOST, ONSITE_PORT, customer_id)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Load a photo.
with open(photo_file_path, 'rb') as photo:
    
    # Create a session. This will persist cookies across all requests.
    session = requests.Session()
    session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
    session.headers.update({
        'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
        'x-pappid': APP_PRIVATE_ID})
    session.verify = False
    
    # Lock the customer before making the change.
    lock_response = session.request('LOCK', customer_url)
    assert lock_response.status_code == 200
    
    # Send the request to add the customer photo.
    post_response = session.post(customer_url + 'customer_photo/', data=photo)
    assert post_response.status_code == 201
    
    # Unlock the customer after the change is complete.
    unlock_response = session.request('UNLOCK', customer_url)
    assert unlock_response.status_code == 200

    # Log out.
    logout_response = session.post(logout_url)
    assert logout_response.status_code == 204
    
    # Get the response and print it.
    response_xml = minidom.parseString(post_response.text)
    print(response_xml.toprettyxml())
<!-- Response -->

<customer id="15" uri="https://localhost:9630/api/customers/15/">
   <created>2017-07-20T12:09:11.341236</created>
   <modified>2017-07-20T13:53:33.470925</modified>
   <name>
       <first>Jane</first>
       <last>Smith</last>
   </name>
   <company/>
   <email>[email protected]</email>
   <homepage>www.example.com</homepage>
   <phone_numbers>
       <phone_number id="1">
           <main>true</main>
           <type>home</type>
           <list_order>1</list_order>
           <number>613-555-5555</number>
       </phone_number>
       <phone_number id="2">
           <main>false</main>
           <type/>
           <list_order>2</list_order>
           <number/>
       </phone_number>
       <phone_number id="3">
           <main>false</main>
           <type/>
           <list_order>3</list_order>
           <number/>
       </phone_number>
       <phone_number id="4">
           <main>false</main>
           <type/>
           <list_order>4</list_order>
           <number/>
       </phone_number>
   </phone_numbers>
   <photo uri="https://localhost:9630/api/customers/15/customer_photo/"/>
   <is_company>false</is_company>
   <billing>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </billing>
   <shipping>
       <address>
           <address1/>
           <address2/>
           <city/>
           <state/>
           <country/>
           <zip/>
       </address>
   </shipping>
   <credit_hold>false</credit_hold>
   <new_import>false</new_import>
   <new_update>false</new_update>
   <birthday/>
   <credit_limit>0.00</credit_limit>
   <customer_id>C-15</customer_id>
   <credit_status uri="https://localhost:9630/api/customers/15/credit_status/"/>
   <ar_balance uri="https://localhost:9630/api/customers/15/ar_balance/"/>
   <import_id/>
   <account_status id="0" uri="https://localhost:9630/api/setup/account_statuses/0/">
       <name>None</name>
       <list_order>0</list_order>
   </account_status>
   <user/>
   <customer_category id="0" uri="https://localhost:9630/api/setup/customer_categories/0/">
       <name>None</name>
       <discount>
           <percent>0.000</percent>
       </discount>
       <pricing_level/>
   </customer_category>
   <customer_referredby id="0" uri="https://localhost:9630/api/setup/customer_referredbys/0/">
       <name>None</name>
   </customer_referredby>
   <currency id="0" uri="https://localhost:9630/api/setup/currencies/0/"/>
   <tax_code id="0" uri="https://localhost:9630/api/tax_codes/0/"/>
   <tax_exemption id="0" uri="https://localhost:9630/api/setup/tax_exemptions/0/"/>
   <terms id="0" uri="https://localhost:9630/api/setup/terms/0/"/>
   <language>
       <id>0</id>
       <language_name>English</language_name>
   </language>
   <notes/>
   <merged_to>
       <customer/>
   </merged_to>
</customer>

Note

There is only one photo per customer.

Downloading a Customer Photo

A GET request to /api/customers/{customer id}/customer_photo/ is used to get a customer photo.

"""
Get a customer photo using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customer_id = 15
customer_photo_url = 'https://%s:%d/api/customers/%d/customer_photo/' % (ONSITE_HOST, ONSITE_PORT, customer_id)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Setup a session for the http request.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False
session.stream = True

# Send the request to get a product photo.
with session.get(customer_photo_url) as response:
    
    # Assert that the request was successful.
    assert response.status_code == 200
    
    # Save the photo to disk.
    with open('customer-photo.jpg', 'wb') as photo:
        for raw_data in response.iter_content(chunk_size=1024):
            photo.write(raw_data)
    
    print('Downloaded customer-photo.jpg')

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

The downloaded image:

Downloaded image

Updating a Customer Photo

A PUT request to /api/customers/{id}/customer_photo/ is used to update a customer photo.

This must be preceded by a LOCK request to the same endpoint, and followed by an UNLOCK request. See Locking & Unlocking Resources.

"""
Update a customer photo using the OnSite API.
"""
import requests

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

photo_file_path = 'images/sample-photo.jpg'
customer_id = 12
customer_url = 'https://%s:%d/api/customers/%d/' % (ONSITE_HOST, ONSITE_PORT, customer_id)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Load a photo.
with open(photo_file_path, 'rb') as photo:
    # Create a session. This will persist cookies across all requests.
    session = requests.Session()
    session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
    session.headers.update({
        'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
        'x-pappid': APP_PRIVATE_ID})
    session.verify = False
    
    # Lock the customer before making the change.
    lock_response = session.request('LOCK', customer_url)
    assert lock_response.status_code == 200
    
    # Send the request to add the customer photo.
    put_response = session.put(customer_url + 'customer_photo/', data=photo)
    assert put_response.status_code == 204
    
    # Unlock the customer after the change is complete.
    unlock_response = session.request('UNLOCK', customer_url)
    assert unlock_response.status_code == 200

    # Log out.
    logout_response = session.post(logout_url)
    assert logout_response.status_code == 204
    
    print("Photo updated.")

Searching Customers

A POST request to /api/customers/search/ is used to search customers. The POST request payload specifies what customer information to return (columns) and what to search by (filters). Pagination is supported with the search query.

A GET request to /api/customers/search/ is used to obtain the list of columns and filters.

Listing Search Columns and Filters

A GET request to /api/customers/search/ is used to obtain the list of columns and filters.

These results can be cached if desired.

"""
Get the list of search filters and columns for customers using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customer_search_url = 'https://%s:%d/api/customers/search/' % (ONSITE_HOST, ONSITE_PORT)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# Create a session. This will persist cookies across all requests.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False

# Send the request to get the list of columns/filters.
get_response = session.get(customer_search_url)
assert get_response.status_code == 200

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Print the list of columns/filters.
response_xml = minidom.parseString(get_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<?xml version="1.0" ?>
<search_criteria uri="https://localhost:9630/api/customers/search/">
	<columns>
		<column id="lsserver.search.column.id">
			<name>
				<localizable_message type="lsserver.search.column.id">
					<fields/>
					<plain_message>ID</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.name">
			<name>
				<localizable_message type="lsserver.search.column.name">
					<fields/>
					<plain_message>Name</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>true</default>
			<sort_default>true</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.email">
			<name>
				<localizable_message type="lsserver.search.column.email">
					<fields/>
					<plain_message>Email</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>true</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.phone">
			<name>
				<localizable_message type="lsserver.search.column.phone">
					<fields/>
					<plain_message>Phone</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>true</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.account_status">
			<name>
				<localizable_message type="lsserver.search.column.account_status">
					<fields/>
					<plain_message>Account Status</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.category">
			<name>
				<localizable_message type="lsserver.search.column.category">
					<fields/>
					<plain_message>Category</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.city">
			<name>
				<localizable_message type="lsserver.search.column.city">
					<fields/>
					<plain_message>City</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.country">
			<name>
				<localizable_message type="lsserver.search.column.country">
					<fields/>
					<plain_message>Country</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.salesperson">
			<name>
				<localizable_message type="lsserver.search.column.salesperson">
					<fields/>
					<plain_message>Salesperson</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.state_province">
			<name>
				<localizable_message type="lsserver.search.column.state_province">
					<fields/>
					<plain_message>State/Province</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
		<column id="lsserver.search.column.company">
			<name>
				<localizable_message type="lsserver.search.column.company">
					<fields/>
					<plain_message>Company</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
			<required>false</required>
			<default>false</default>
			<sort_default>false</sort_default>
			<sort_default_order_by>ASC</sort_default_order_by>
			<can_summarize>false</can_summarize>
		</column>
	</columns>
	<filters>
		<filter id="lsserver.search.filters.account_status">
			<name>
				<localizable_message type="lsserver.search.filters.account_status">
					<fields/>
					<plain_message>Account Status</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.address">
			<name>
				<localizable_message type="lsserver.search.filters.address">
					<fields/>
					<plain_message>Address</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.customer">
			<name>
				<localizable_message type="lsserver.search.filters.customer">
					<fields/>
					<plain_message>Customer</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.category">
			<name>
				<localizable_message type="lsserver.search.filters.category">
					<fields/>
					<plain_message>Category</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.city">
			<name>
				<localizable_message type="lsserver.search.filters.city">
					<fields/>
					<plain_message>City</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.country">
			<name>
				<localizable_message type="lsserver.search.filters.country">
					<fields/>
					<plain_message>Country</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.currency">
			<name>
				<localizable_message type="lsserver.search.filters.currency">
					<fields/>
					<plain_message>Currency</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.customer_id">
			<name>
				<localizable_message type="lsserver.search.filters.customer_id">
					<fields/>
					<plain_message>Customer ID</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.created_date">
			<name>
				<localizable_message type="lsserver.search.filters.created_date">
					<fields/>
					<plain_message>Created Date</plain_message>
				</localizable_message>
			</name>
			<type>DATE</type>
		</filter>
		<filter id="lsserver.search.filters.email">
			<name>
				<localizable_message type="lsserver.search.filters.email">
					<fields/>
					<plain_message>Email</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.groups">
			<name>
				<localizable_message type="lsserver.search.filters.groups">
					<fields/>
					<plain_message>Groups</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.home_page">
			<name>
				<localizable_message type="lsserver.search.filters.home_page">
					<fields/>
					<plain_message>Home Page</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.company">
			<name>
				<localizable_message type="lsserver.search.filters.company">
					<fields/>
					<plain_message>Company</plain_message>
				</localizable_message>
			</name>
			<type>BOOLEAN</type>
		</filter>
		<filter id="lsserver.search.filters.name">
			<name>
				<localizable_message type="lsserver.search.filters.name">
					<fields/>
					<plain_message>Name</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.new_import">
			<name>
				<localizable_message type="lsserver.search.filters.new_import">
					<fields/>
					<plain_message>New Import</plain_message>
				</localizable_message>
			</name>
			<type>BOOLEAN</type>
		</filter>
		<filter id="lsserver.search.filters.new_updates">
			<name>
				<localizable_message type="lsserver.search.filters.new_updates">
					<fields/>
					<plain_message>New Updates</plain_message>
				</localizable_message>
			</name>
			<type>BOOLEAN</type>
		</filter>
		<filter id="lsserver.search.filters.notes">
			<name>
				<localizable_message type="lsserver.search.filters.notes">
					<fields/>
					<plain_message>Notes</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.merged">
			<name>
				<localizable_message type="lsserver.search.filters.merged">
					<fields/>
					<plain_message>Merged</plain_message>
				</localizable_message>
			</name>
			<type>BOOLEAN</type>
		</filter>
		<filter id="lsserver.search.filters.modified_date">
			<name>
				<localizable_message type="lsserver.search.filters.modified_date">
					<fields/>
					<plain_message>Modified Date</plain_message>
				</localizable_message>
			</name>
			<type>DATE</type>
		</filter>
		<filter id="lsserver.search.filters.phone">
			<name>
				<localizable_message type="lsserver.search.filters.phone">
					<fields/>
					<plain_message>Phone</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.referred_by">
			<name>
				<localizable_message type="lsserver.search.filters.referred_by">
					<fields/>
					<plain_message>Referred By</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.salesperson">
			<name>
				<localizable_message type="lsserver.search.filters.salesperson">
					<fields/>
					<plain_message>Salesperson</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.state_province">
			<name>
				<localizable_message type="lsserver.search.filters.state_province">
					<fields/>
					<plain_message>State/Province</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.tax_code">
			<name>
				<localizable_message type="lsserver.search.filters.tax_code">
					<fields/>
					<plain_message>Tax Code</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.tax_status">
			<name>
				<localizable_message type="lsserver.search.filters.tax_status">
					<fields/>
					<plain_message>Tax Status</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.terms">
			<name>
				<localizable_message type="lsserver.search.filters.terms">
					<fields/>
					<plain_message>Terms</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
		<filter id="lsserver.search.filters.zip_postal_code">
			<name>
				<localizable_message type="lsserver.search.filters.zip_postal_code">
					<fields/>
					<plain_message>Zip/Postal Code</plain_message>
				</localizable_message>
			</name>
			<type>STRING</type>
		</filter>
	</filters>
</search_criteria>

Search by Name

A POST request to /api/customers/search/ is used to search customers.

"""
Search customers using the OnSite API.
"""
import requests
from xml.dom import minidom

# Customize these to your install.
ONSITE_HOST = 'localhost'
ONSITE_PORT = 9630
ONSITE_USERNAME = 'lightspeed'
ONSITE_PASSWORD = 'admin'
APP_ID = 'com.lightspeed.onsite.demo'
APP_VERSION = '1.0'
APP_PRIVATE_ID = '12345678-90ab-cdef-1234-567890abcdef'

customer_search_url = 'https://%s:%d/api/customers/search/' % (ONSITE_HOST, ONSITE_PORT)
logout_url = 'https://%s:%d/api/sessions/current/logout/' % (ONSITE_HOST, ONSITE_PORT)

# This is the search information.
search_xml = """
<search>
    <page>
        <offset>0</offset>
        <count>5</count>
    </page>
    <search_query>
        <columns>
            <column id="lsserver.search.column.id"/>
            <column id="lsserver.search.column.name"/>
            <column id="lsserver.search.column.phone"/>
            <column id="lsserver.search.column.city"/>
        </columns>
        <sort_by_column>
            <column id="lsserver.search.column.name"/>
            <order_by>ASC</order_by>
        </sort_by_column>
        <filters>lsserver.search.filters.name CONTAINS 'Smith'</filters>
    </search_query>
</search>
"""

# Create a session. This will persist cookies across all requests.
session = requests.Session()
session.auth = (ONSITE_USERNAME, ONSITE_PASSWORD)
session.headers.update({
    'user-agent': '%s/%s' % (APP_ID, APP_VERSION),
    'x-pappid': APP_PRIVATE_ID})
session.verify = False

# Send the request to search the customers.
post_response = session.post(customer_search_url, data=search_xml)
assert post_response.status_code == 200

# Log out.
logout_response = session.post(logout_url)
assert logout_response.status_code == 204

# Print the search results.
response_xml = minidom.parseString(post_response.text)
print(response_xml.toprettyxml())
<!-- Response -->

<?xml version="1.0" ?>
<data>
   <info>
       <total_count>1</total_count>
   </info>
   <columns>
       <column>
           <name>
               <localizable_message type="lsserver.search.column.id">
                   <fields/>
                   <plain_message>ID</plain_message>
               </localizable_message>
           </name>
           <type>STRING</type>
       </column>
       <column>
           <name>
               <localizable_message type="lsserver.search.column.name">
                   <fields/>
                   <plain_message>Name</plain_message>
               </localizable_message>
           </name>
           <type>STRING</type>
       </column>
       <column>
           <name>
               <localizable_message type="lsserver.search.column.phone">
                   <fields/>
                   <plain_message>Phone</plain_message>
               </localizable_message>
           </name>
           <type>STRING</type>
       </column>
       <column>
           <name>
               <localizable_message type="lsserver.search.column.city">
                   <fields/>
                   <plain_message>City</plain_message>
               </localizable_message>
           </name>
           <type>STRING</type>
       </column>
   </columns>
   <rows>
       <row>
           <links>
               <link>
                   <customer id="15" uri="https://localhost:9630/api/customers/15/"/>
               </link>
           </links>
           <cell>
               <type>STRING</type>
               <value>C-15</value>
           </cell>
           <cell>
               <type>STRING</type>
               <value>Jane Smith</value>
           </cell>
           <cell>
               <type>STRING</type>
               <value>613-555-5555</value>
           </cell>
           <cell>
               <type>STRING</type>
               <value/>
           </cell>
       </row>
   </rows>
</data>