Easy interface to work with the Close.io API.
Project description
Close[.]io
Simpler and saner interface for working with the Close API
Features:
- Automatic create or update of a resource.
- Automatic schema creation for (most) Close resources with IDE autocomplete.
- Extendable Lead and Contact model to match your Close custom fields.
- Retry/rate-limit handling.
Installation
pip install close-dot-io
Basic Usage
Getting a list of a resource
from close_dot_io import CloseClient, Lead
CLOSE_API_KEY = "MY-KEY-HERE"
# Create a connection to Close.
client = CloseClient(
api_key=CLOSE_API_KEY
)
# Get 200 leads.
# You get a list of 'Lead' object with the expected Python data types.
leads:list[Lead] = client.list(resource=Lead, max_results=200)
print(leads)
# > [
# Lead(
# id='lead_xxx',
# status_label='Cold',
# description='A sales automation ...',
# html_url='https://app.close.com/leads/lead_xx',
# organization_id='orga_xxx',
# date_updated=datetime.datetime(2024, 4, 14, 17, 43, 38, 77000, tzinfo=TzInfo(UTC)),
# date_created=datetime.datetime(2024, 2, 29, 11, 3, 12, 544000, tzinfo=TzInfo(UTC)),
# name='Copyfactory Technologies',
# contacts=[
# Contact(id='cont_xxx',
# organization_id='orga_xxx',
# date_updated=datetime.datetime(2024, 4, 10, 19, 1, 30, 512000, tzinfo=TzInfo(UTC)),
# date_created=datetime.datetime(2024, 2, 29, 11, 3, 12, 557000, tzinfo=TzInfo(UTC)),
# name='Eric Morris',
# title='co-founder',
# phones=[
# ContactPhoneNumber(
# country='CA',
# phone='+16xxx',
# type=<ContactEmailOrPhoneTypeEnum.OFFICE: 'office'>
# )
# ],
# emails=[
# ContactEmailAddress(
# type=<ContactEmailOrPhoneTypeEnum.OFFICE: 'office'>,
# email='eric@cf.io',
# is_unsubscribed=False
# )
# ]
# )
# ])] ...
# Get the first leads ID.
first_lead = leads[0].id
# Iterate over leads and contacts
for lead in leads:
for contact in lead.contacts:
...
Currently supported resources are:
from close_dot_io import (
Lead,
Contact,
ConnectedAccount,
Sequence,
CallActivity,
CreatedActivity,
EmailActivity,
EmailThreadActivity,
LeadStatusChangeActivity,
MeetingActivity,
NoteActivity,
OpportunityStatusChangeActivity,
SMSActivity,
TaskCompletedActivity,
SmartView
)
Getting a list of leads based on a smartview.
from close_dot_io import CloseClient
CLOSE_API_KEY = "MY-KEY-HERE"
# Create a connection to Close.
client = CloseClient(
api_key=CLOSE_API_KEY
)
# By id
leads = client.get_from_smartview(smartview_id="save_xxx", max_results=10)
# Or search by name (slower since we need to fetch the smartviews to grab the ID)
leads = client.get_from_smartview(smartview_name="People to follow up with", max_results=10)
Creating/Updating/Cloning a new contact/lead
from close_dot_io import CloseClient, Contact, Lead
CLOSE_API_KEY = "MY-KEY-HERE"
# Create a connection to Close.
client = CloseClient(
api_key=CLOSE_API_KEY
)
# Create using only an Email.
new_contact = Contact.create_from_email(email="j@acme.com", title='CEO')
# Assign contact to lead.
new_lead = Lead.create_from_contact(new_contact, name="Acme Corp")
# Notice how these are bare objects since they do not have a Close id.
print(new_lead.id)
print(new_contact.id)
# > None
# > None
# Lets save the new Lead to Close.
new_lead = client.save(resource=new_lead)
# Now if we print out the ID again we have an ID!
print(new_lead.id)
# > lead_xxx
# We can now easily edit our new lead
new_lead.name = "Acme Corp Edited from API!"
# And save it. Since the resource has an ID an update is performed.
updated_lead = client.save(resource=new_lead)
# This means cloning is very easy. Just reset the ID and save it again.
updated_lead.id = None
cloned_lead = client.save(resource=new_lead)
Extending the Contact and Lead resource
You likely have some custom fields that you want to use for your Contacts and Leads.
Here is how to do that.
Under the hood Pydantic is used to validate models and type annotations.
from close_dot_io import Contact, Lead, CloseClient
from pydantic import Field
from enum import Enum
# Subclass the base Contact object
class MyCustomContact(Contact):
# The name can be anything you want.
# The only required steps are to (1) set the 'alias' parameter with the custom field ID.
# and (2) set a type annotation to the field.
# You can copy the ID in the Close custom field settings.
# **Important** you must prefix the custom field ID with 'custom.{my-id}'
# Its recommended to set the default to None since your field is likely optional.
some_custom_field: str | None = Field(
alias="custom.cf_xxx",
default=None,
description="My awesome custom field.",
)
# Number fields are also fine. Set a default if its applicable.
external_funding: int | None = Field(
alias="custom.cf_xxx",
default=0,
description="Enrichment field for if the contact has received funding.",
)
# Decimals are fine too.
customer_discount: float | None = Field(
alias="custom.cf_xxx",
default=0.1,
description="The discount amount a customer is to receive",
)
class CustomerServiceRep(Enum):
ALICE = "rep_id_1"
CAM = "rep_id_2"
# You can also 'nest' your own models based on your use case or contact pipeline stages.
class PostCustomerContactModel(MyCustomContact):
# Choices also work.
customer_rep: CustomerServiceRep | None = Field(
alias="custom.cf_xxx",
default=CustomerServiceRep.ALICE,
description="The ID of the CS rep asigned to this contact.",
)
# Same exact logic applies to a Lead.
class CustomLead(Lead):
lead_score: int | None = Field(alias="custom.cf_xxx", default=None)
# Now you just create these as you would any other object.
new_contact = PostCustomerContactModel.create_from_email(
email="j@customer.com",
title='CEO',
customer_rep=CustomerServiceRep.CAM
)
new_lead = CustomLead.create_from_contact(
new_contact,
status_label='Customer',
name="Acme Corp",
lead_score=1
)
CLOSE_API_KEY = "MY-KEY-HERE"
# To save you need to bind your custom Contact and Lead models to the client.
# Now whenever you ask for Leads or Contacts
# you will get the bound object returned with all the custom fields automatically transposed.
client = CloseClient(
api_key=CLOSE_API_KEY,
contact_model=PostCustomerContactModel,
lead_model=CustomLead
)
client.save(new_lead)
Huge thank you to the Close team for creating a best-in-class product and API!
Close API documentation: https://developer.close.com/
License
close-dot-io
is distributed under the terms of the MIT license.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
close_dot_io-0.0.8.tar.gz
(11.9 kB
view details)
Built Distribution
File details
Details for the file close_dot_io-0.0.8.tar.gz
.
File metadata
- Download URL: close_dot_io-0.0.8.tar.gz
- Upload date:
- Size: 11.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.27.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 68de74a47301ed367af8d71e3e68bb5cc05391498cf7d0adad1b811d5c69c334 |
|
MD5 | 6559e46c3fa78f45a12566a6fa42fbb3 |
|
BLAKE2b-256 | 8f8b4222a2c5153448d88ca20358909a903ba6a64b88dbc4548ef553ef481179 |
File details
Details for the file close_dot_io-0.0.8-py3-none-any.whl
.
File metadata
- Download URL: close_dot_io-0.0.8-py3-none-any.whl
- Upload date:
- Size: 14.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: python-httpx/0.27.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 5cab74604c45328c1e48fa7f511ad5d6b5f0140af66e46337508281dad780c33 |
|
MD5 | e5194322346cb737ac539de76f3d1bf9 |
|
BLAKE2b-256 | 1ad8651085dfa4e2c3fbc6341dd12f3130a12a4de013b9f28982ed3190b48bb3 |