├── .gitignore ├── LICENSE.txt ├── README.md ├── pypardot ├── __init__.py ├── client.py ├── errors.py └── objects │ ├── __init__.py │ ├── accounts.py │ ├── campaigns.py │ ├── emails.py │ ├── lists.py │ ├── opportunities.py │ ├── prospects.py │ ├── tests │ ├── .gitignore │ ├── README.md │ ├── __init__.py │ ├── config.py.example │ └── test_prospects.py │ ├── users.py │ ├── visitoractivities.py │ ├── visitors.py │ └── visits.py ├── setup.cfg └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Python byte code files 2 | *.pyc 3 | 4 | # Emacs save files 5 | *~ 6 | 7 | # OSX directory meta files 8 | .DS_Store 9 | 10 | # Python egg metadata 11 | *.egg-info 12 | 13 | # PyCharm / Jetbrains IDE 14 | .idea -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Josh Geller 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | PyPardot 2 | ========= 3 | 4 | ### Note: Deprecated! See [PyPardot4](https://github.com/mneedham91/PyPardot4/) for API v4 support. 5 | 6 | PyPardot is an API wrapper for [Pardot](http://www.pardot.com/), written in Python. 7 | 8 | Using it is simple: 9 | 10 | ``` 11 | from pypardot.client import PardotAPI 12 | 13 | 14 | p = PardotAPI( 15 | email='your_pardot_email', 16 | password='your_pardot_password', 17 | user_key='your_pardot_user_key' 18 | ) 19 | 20 | p.authenticate() 21 | 22 | # Create a new prospect 23 | p.prospects.create_by_email(email='joe@company.com', first_name='Joe', last_name='Schmoe') 24 | 25 | # Update a prospect field 26 | p.prospects.update_field_by_email(email='joe@company.com', field='company', field_value='Joes Plumbing') 27 | 28 | # Update or create a prospect 29 | p.prospects.upsert_by_email(email='joe@company.com', first_name='Joe', last_name='Schmoe') 30 | 31 | # Send a one-off email 32 | p.emails.send_to_email(prospect_email='joe@company.com', email_template_id=123, campaign_id=456) 33 | ``` 34 | 35 | Features 36 | --- 37 | 38 | + Includes all documented Pardot API operations 39 | + Handles API key expiration 40 | + Detailed API error handling 41 | 42 | Object Types & Operations 43 | --- 44 | 45 | Support for the following object types: 46 | 47 | + Accounts 48 | + Emails 49 | + Lists 50 | + Opportunities 51 | + Prospects 52 | + Users 53 | + Visitor Activities 54 | + Visitors 55 | + Visits 56 | 57 | Required 58 | --- 59 | 60 | + [requests](http://docs.python-requests.org/en/latest/) 61 | 62 | Installation 63 | --- 64 | 65 | Install PyPardot by running: 66 | ``` 67 | pip install pypardot 68 | ``` 69 | 70 | Usage 71 | --- 72 | 73 | ###Authentication 74 | 75 | To connect to the Pardot API, you'll need the e-mail address, password, and user key associated with your Pardot account. Your user key is available in the Pardot application under My Settings. 76 | 77 | The client will authenticate before performing other API calls, but you can manually authenticate as well: 78 | 79 | 80 | ``` 81 | p = PardotAPI( 82 | email='your_pardot_email', 83 | password='your_pardot_password', 84 | user_key='your_pardot_user_key' 85 | ) 86 | 87 | p.authenticate() 88 | ``` 89 | 90 | ###Querying Objects 91 | 92 | Supported search criteria varies for each object. Check the [official Pardot API documentation](http://developer.pardot.com/kb/api-version-3/introduction-table-of-contents) for supported parameters. Most objects support `limit`, `offset`, `sort_by`, and `sort_order` parameters. PyPardot returns JSON for all API queries. 93 | 94 | **Note**: Pardot only returns 200 records with each request. Use `offset` to retrieve matching records beyond this limit. 95 | 96 | ``` 97 | # Query and iterate through today's prospects 98 | prospects = p.prospects.query(created_after='yesterday') 99 | total = prospects['total_results'] # total number of matching records 100 | for prospect in prospects['prospect'] 101 | print(prospect.get('first_name')) 102 | ``` 103 | 104 | ### Editing/Updating/Reading Objects 105 | 106 | Supported fields varies for each object. Check the [official Pardot API documentation](http://developer.pardot.com/kb/api-version-3/introduction-table-of-contents) to see the fields associated with each object. 107 | 108 | ``` 109 | # Create a new prospect 110 | p.prospects.create_by_email(email='joe@company.com', first_name='Joe', last_name='Schmoe') 111 | 112 | # Update a prospect field (works with default or custom field) 113 | p.prospects.update_field_by_email(email='joe@company.com', field='company', field_value='Joes Plumbing') 114 | 115 | # Send a one-off email 116 | p.emails.send_to_email(prospect_email='joe@company.com', email_template_id=123) 117 | ``` 118 | 119 | ### Extras 120 | 121 | PyPardot supports some un-documented API methods: 122 | 123 | + `prospects.add_to_list`: Adds the prospect to a Pardot list 124 | + `prospects.update_field_by_email`: Updates the value for a single default or custom field 125 | + `prospects.read_field_by_email`: Returns the value for a single default or custom field 126 | + More coming soon! 127 | 128 | ### Error Handling 129 | 130 | #### Handling expired API keys 131 | 132 | Pardot API keys expire after 60 minutes. If PyPardot detects an 'Invalid API key' error during any API call, it will automatically attempt to re-authenticate and obtain a new valid API key. If re-authentication is successful, the API call will be re-issued. If re-authentication fails, a `PardotAPIError` is thrown. 133 | 134 | #### Invalid API parameters 135 | 136 | If an API call is made with missing or invalid parameters, a `PardotAPIError` is thrown. Error instances contain the error code and message corresponding to error response returned by the API. See [Pardot Error Codes & Messages](http://developer.pardot.com/kb/api-version-3/error-codes-and-messages) in the official documentation. 137 | 138 | Performing API calls is inherently unsafe, so be sure to catch exceptions: 139 | 140 | ``` 141 | try: 142 | p.prospects.create_by_email(email='existing.email.address@company.com') 143 | except PardotAPIError, e: 144 | print(e) 145 | ``` 146 | -------------------------------------------------------------------------------- /pypardot/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshgeller/PyPardot/349dde1fad561f32a425324005c4f2a0c4a23d9b/pypardot/__init__.py -------------------------------------------------------------------------------- /pypardot/client.py: -------------------------------------------------------------------------------- 1 | import requests 2 | from .objects.lists import Lists 3 | from .objects.emails import Emails 4 | from .objects.prospects import Prospects 5 | from .objects.opportunities import Opportunities 6 | from .objects.accounts import Accounts 7 | from .objects.users import Users 8 | from .objects.visits import Visits 9 | from .objects.visitors import Visitors 10 | from .objects.visitoractivities import VisitorActivities 11 | from .objects.campaigns import Campaigns 12 | 13 | from .errors import PardotAPIError 14 | 15 | # Issue #1 (http://code.google.com/p/pybing/issues/detail?id=1) 16 | # Python 2.6 has json built in, 2.5 needs simplejson 17 | try: 18 | import json 19 | except ImportError: 20 | import simplejson as json 21 | 22 | BASE_URI = 'https://pi.pardot.com' 23 | 24 | 25 | class PardotAPI(object): 26 | def __init__(self, email, password, user_key): 27 | self.email = email 28 | self.password = password 29 | self.user_key = user_key 30 | self.api_key = None 31 | self.lists = Lists(self) 32 | self.emails = Emails(self) 33 | self.prospects = Prospects(self) 34 | self.opportunities = Opportunities(self) 35 | self.accounts = Accounts(self) 36 | self.users = Users(self) 37 | self.visits = Visits(self) 38 | self.visitors = Visitors(self) 39 | self.visitoractivities = VisitorActivities(self) 40 | self.campaigns = Campaigns(self) 41 | 42 | def post(self, object_name, path=None, params=None, retries=0): 43 | """ 44 | Makes a POST request to the API. Checks for invalid requests that raise PardotAPIErrors. If the API key is 45 | invalid, one re-authentication request is made, in case the key has simply expired. If no errors are raised, 46 | returns either the JSON response, or if no JSON was returned, returns the HTTP response status code. 47 | """ 48 | if params is None: 49 | params = {} 50 | params.update({'user_key': self.user_key, 'api_key': self.api_key, 'format': 'json'}) 51 | try: 52 | self._check_auth(object_name=object_name) 53 | request = requests.post(self._full_path(object_name, path), params=params) 54 | response = self._check_response(request) 55 | return response 56 | except PardotAPIError as err: 57 | if err.message == 'Invalid API key or user key': 58 | response = self._handle_expired_api_key(err, retries, 'post', object_name, path, params) 59 | return response 60 | else: 61 | raise err 62 | 63 | def get(self, object_name, path=None, params=None, retries=0): 64 | """ 65 | Makes a GET request to the API. Checks for invalid requests that raise PardotAPIErrors. If the API key is 66 | invalid, one re-authentication request is made, in case the key has simply expired. If no errors are raised, 67 | returns either the JSON response, or if no JSON was returned, returns the HTTP response status code. 68 | """ 69 | if params is None: 70 | params = {} 71 | params.update({'user_key': self.user_key, 'api_key': self.api_key, 'format': 'json'}) 72 | try: 73 | self._check_auth(object_name=object_name) 74 | request = requests.get(self._full_path(object_name, path), params=params) 75 | response = self._check_response(request) 76 | return response 77 | except PardotAPIError as err: 78 | if err.message == 'Invalid API key or user key': 79 | response = self._handle_expired_api_key(err, retries, 'get', object_name, path, params) 80 | return response 81 | else: 82 | raise err 83 | 84 | def _handle_expired_api_key(self, err, retries, method, object_name, path, params): 85 | """ 86 | Tries to refresh an expired API key and re-issue the HTTP request. If the refresh has already been attempted, 87 | an error is raised. 88 | """ 89 | if retries != 0: 90 | raise err 91 | self.api_key = None 92 | if self.authenticate(): 93 | response = getattr(self, method)(object_name=object_name, path=path, params=params, retries=1) 94 | return response 95 | else: 96 | raise err 97 | 98 | @staticmethod 99 | def _full_path(object_name, path=None, version=3): 100 | """Builds the full path for the API request""" 101 | full = '{0}/api/{1}/version/{2}'.format(BASE_URI, object_name, version) 102 | if path: 103 | return full + '{0}'.format(path) 104 | return full 105 | 106 | @staticmethod 107 | def _check_response(response): 108 | """ 109 | Checks the HTTP response to see if it contains JSON. If it does, checks the JSON for error codes and messages. 110 | Raises PardotAPIError if an error was found. If no error was found, returns the JSON. If JSON was not found, 111 | returns the response status code. 112 | """ 113 | if response.headers.get('content-type') == 'application/json': 114 | json = response.json() 115 | error = json.get('err') 116 | if error: 117 | raise PardotAPIError(json_response=json) 118 | return json 119 | else: 120 | return response.status_code 121 | 122 | def _check_auth(self, object_name): 123 | if object_name == 'login': 124 | return 125 | if self.api_key is None: 126 | self.authenticate() 127 | 128 | def authenticate(self): 129 | """ 130 | Authenticates the user and sets the API key if successful. Returns True if authentication is successful, 131 | False if authentication fails. 132 | """ 133 | try: 134 | auth = self.post('login', params={'email': self.email, 'password': self.password}) 135 | self.api_key = auth.get('api_key') 136 | if self.api_key is not None: 137 | return True 138 | return False 139 | except PardotAPIError: 140 | return False 141 | -------------------------------------------------------------------------------- /pypardot/errors.py: -------------------------------------------------------------------------------- 1 | class PardotAPIError(Exception): 2 | """ 3 | Basic exception class for errors encountered in API post and get requests. Takes the json response and parses out 4 | the error code and message. 5 | """ 6 | 7 | def __init__(self, json_response): 8 | self.response = json_response 9 | self.err_code = json_response.get('@attributes').get('err_code') 10 | self.message = str(json_response.get('err')) 11 | if self.err_code is None: 12 | self.err_code = 0 13 | self.message = 'Unknown API error occurred' 14 | 15 | def __str__(self): 16 | return 'Error #{err_code}: {message}'.format(err_code=self.err_code, message=self.message) 17 | 18 | 19 | class PardotAPIArgumentError(Exception): 20 | pass 21 | -------------------------------------------------------------------------------- /pypardot/objects/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshgeller/PyPardot/349dde1fad561f32a425324005c4f2a0c4a23d9b/pypardot/objects/__init__.py -------------------------------------------------------------------------------- /pypardot/objects/accounts.py: -------------------------------------------------------------------------------- 1 | class Accounts(object): 2 | """ 3 | A class to query and use Pardot accounts. 4 | Account field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#prospectAccount 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the prospect accounts matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/prospect-accounts/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['prospectAccount'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['prospectAccount'] = [] 21 | elif result['total_results'] == 1: 22 | result['prospectAccount'] = [result['prospectAccount']] 23 | 24 | return result 25 | 26 | def create(self, **kwargs): 27 | """Creates a new prospect account.""" 28 | response = self._post(path='/do/create', params=kwargs) 29 | return response 30 | 31 | def describe(self, **kwargs): 32 | """ 33 | Returns the field metadata for prospect accounts, explaining what fields are available, their types, whether 34 | they are required, and their options (for dropdowns, radio buttons, etc). 35 | """ 36 | response = self._get(path='/do/describe', params=kwargs) 37 | return response 38 | 39 | def read(self, id=None, **kwargs): 40 | """ 41 | Returns the data for the prospect account specified by . is the Pardot ID of the target prospect 42 | account. 43 | """ 44 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 45 | return response 46 | 47 | def update(self, id=None, **kwargs): 48 | """ 49 | Updates the data for the prospect account specified by . is the Pardot ID of the target prospect 50 | account. 51 | """ 52 | response = self._post(path='/do/update/id/{id}'.format(id=id), params=kwargs) 53 | return response 54 | 55 | def _get(self, object_name='prospectAccount', path=None, params=None): 56 | """GET requests for the Account object.""" 57 | if params is None: 58 | params = {} 59 | response = self.client.get(object_name=object_name, path=path, params=params) 60 | return response 61 | 62 | def _post(self, object_name='prospectAccount', path=None, params=None): 63 | """POST requests for the Account object.""" 64 | if params is None: 65 | params = {} 66 | response = self.client.post(object_name=object_name, path=path, params=params) 67 | return response 68 | -------------------------------------------------------------------------------- /pypardot/objects/campaigns.py: -------------------------------------------------------------------------------- 1 | class Campaigns(object): 2 | """ 3 | A class to query and use Pardot campaigns. 4 | Campaign field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#campaign 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the campaigns matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/campaigns/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['campaign'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['campaign'] = [] 21 | elif result['total_results'] == 1: 22 | result['campaign'] = [result['campaign']] 23 | 24 | return result 25 | 26 | def read_by_id(self, id=None, **kwargs): 27 | """ 28 | Returns the data for the campaign specified by . is the Pardot ID of the target campaign.""" 29 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 30 | return response 31 | 32 | def _get(self, object_name='campaign', path=None, params=None): 33 | """GET requests for the Campaign object.""" 34 | if params is None: 35 | params = {} 36 | response = self.client.get(object_name=object_name, path=path, params=params) 37 | return response 38 | 39 | def _post(self, object_name='campaign', path=None, params=None): 40 | """POST requests for the Campaign object.""" 41 | if params is None: 42 | params = {} 43 | response = self.client.post(object_name=object_name, path=path, params=params) 44 | return response 45 | -------------------------------------------------------------------------------- /pypardot/objects/emails.py: -------------------------------------------------------------------------------- 1 | class Emails(object): 2 | """ 3 | A class to query and send Pardot emails. 4 | Email field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#email 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def send_to_email(self, prospect_email=None, **kwargs): 11 | """ 12 | Sends an email to the prospect identified by . 13 | Required parameters: (email_template_id OR (text_content, name, subject, & ((from_email & from_name) OR from_user_id))) 14 | """ 15 | response = self._post( 16 | path='/do/send/prospect_email/{prospect_email}'.format(prospect_email=prospect_email), 17 | params=kwargs) 18 | return response 19 | 20 | def send_to_id(self, prospect_id=None, **kwargs): 21 | """ 22 | Sends an email to the prospect identified by . 23 | Required parameters: (email_template_id OR (text_content, name, subject, & ((from_email & from_name) OR from_user_id))) 24 | """ 25 | response = self._post( 26 | path='/do/send/prospect_id/{prospect_id}'.format(prospect_id=prospect_id), params=kwargs) 27 | return response 28 | 29 | def send_to_lists(self, **kwargs): 30 | """ 31 | Sends an email to the lists identified by . 32 | Required parameters: (email_template_id OR (text_content, name, subject, & ((from_email & from_name) OR from_user_id))) 33 | """ 34 | kwargs['list_ids'] = kwargs.get('list_ids', None) 35 | response = self._post( 36 | path='/do/send/', params=kwargs) 37 | return response 38 | 39 | def read(self, id=None): 40 | """Returns the data for the email specified by . is the Pardot ID of the target email.""" 41 | response = self._post(path='/do/read/id/{id}'.format(id=id)) 42 | return response 43 | 44 | def _get(self, object_name='email', path=None, params=None): 45 | """GET requests for the Email object.""" 46 | if params is None: 47 | params = {} 48 | response = self.client.get(object_name=object_name, path=path, params=params) 49 | return response 50 | 51 | def _post(self, object_name='email', path=None, params=None): 52 | """POST requests for the Email object.""" 53 | if params is None: 54 | params = {} 55 | response = self.client.post(object_name=object_name, path=path, params=params) 56 | return response 57 | -------------------------------------------------------------------------------- /pypardot/objects/lists.py: -------------------------------------------------------------------------------- 1 | class Lists(object): 2 | """ 3 | A class to query and use Pardot lists. 4 | List field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#list 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the lists matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/lists/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['list'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['list'] = [] 21 | elif result['total_results'] == 1: 22 | result['list'] = [result['list']] 23 | 24 | return result 25 | 26 | def read(self, id=None): 27 | """ 28 | Returns the data for the list specified by . is the Pardot ID of the target list. 29 | """ 30 | response = self._post(path='/do/read/id/{id}'.format(id=id)) 31 | return response 32 | 33 | def _get(self, object_name='list', path=None, params=None): 34 | """GET requests for the List object.""" 35 | if params is None: 36 | params = {} 37 | response = self.client.get(object_name=object_name, path=path, params=params) 38 | return response 39 | 40 | def _post(self, object_name='list', path=None, params=None): 41 | """POST requests for the List object.""" 42 | if params is None: 43 | params = {} 44 | response = self.client.post(object_name=object_name, path=path, params=params) 45 | return response 46 | -------------------------------------------------------------------------------- /pypardot/objects/opportunities.py: -------------------------------------------------------------------------------- 1 | class Opportunities(object): 2 | """ 3 | A class to query and use Pardot opportunities. 4 | Opportunity field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#opportunity 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the opportunities matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/opportunities/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['opportunity'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['opportunity'] = [] 21 | elif result['total_results'] == 1: 22 | result['opportunity'] = [result['opportunity']] 23 | 24 | return result 25 | 26 | def create_by_email(self, prospect_email=None, name=None, value=None, probability=None, **kwargs): 27 | """ 28 | Creates a new opportunity using the specified data. must correspond to an existing prospect. 29 | """ 30 | kwargs.update({'name': name, 'value': value, 'probability': probability}) 31 | response = self._post( 32 | path='/do/create/prospect_email/{prospect_email}'.format(prospect_email=prospect_email), 33 | params=kwargs) 34 | return response 35 | 36 | def create_by_id(self, prospect_id=None, name=None, value=None, probability=None, **kwargs): 37 | """ 38 | Creates a new opportunity using the specified data. must correspond to an existing prospect. 39 | """ 40 | kwargs.update({'name': name, 'value': value, 'probability': probability}) 41 | response = self._post( 42 | path='/do/create/prospect_id/{prospect_id}'.format(prospect_id=prospect_id), 43 | params=kwargs) 44 | return response 45 | 46 | def read(self, id=None): 47 | """ 48 | Returns the data for the opportunity specified by , including campaign assignment and associated visitor 49 | activities. is the Pardot ID for the target opportunity. 50 | """ 51 | response = self._post(path='/do/read/id/{id}'.format(id=id)) 52 | return response 53 | 54 | def update(self, id=None): 55 | """ 56 | Updates the provided data for the opportunity specified by . is the Pardot ID for the target 57 | opportunity. Fields that are not updated by the request remain unchanged. Returns an updated version of the 58 | opportunity. 59 | """ 60 | response = self._post(path='/do/update/id/{id}'.format(id=id)) 61 | return response 62 | 63 | def delete(self, id=None): 64 | """ 65 | Deletes the opportunity specified by . is the Pardot ID for the target opportunity. Returns no response 66 | on success. 67 | """ 68 | response = self._post(path='/do/delete/id/{id}'.format(id=id)) 69 | return response 70 | 71 | def undelete(self, id=None): 72 | """ 73 | Un-deletes the opportunity specified by . is the Pardot ID for the target opportunity. Returns no 74 | response on success. 75 | """ 76 | response = self._post(path='/do/undelete/id/{id}'.format(id=id)) 77 | return response 78 | 79 | def _get(self, object_name='opportunity', path=None, params=None): 80 | """GET requests for the Opportunity object.""" 81 | if params is None: 82 | params = {} 83 | response = self.client.get(object_name=object_name, path=path, params=params) 84 | return response 85 | 86 | def _post(self, object_name='opportunity', path=None, params=None): 87 | """POST requests for the Opportunity object.""" 88 | if params is None: 89 | params = {} 90 | response = self.client.post(object_name=object_name, path=path, params=params) 91 | return response 92 | -------------------------------------------------------------------------------- /pypardot/objects/prospects.py: -------------------------------------------------------------------------------- 1 | from ..errors import PardotAPIArgumentError 2 | 3 | 4 | class Prospects(object): 5 | """ 6 | A class to query and use Pardot prospects. 7 | Prospect field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#prospect 8 | """ 9 | 10 | def __init__(self, client): 11 | self.client = client 12 | 13 | def query(self, **kwargs): 14 | """ 15 | Returns the prospects matching the specified criteria parameters. 16 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/prospects/#supported-search-criteria 17 | """ 18 | response = self._get(path='/do/query', params=kwargs) 19 | 20 | # Ensure result['prospect'] is a list, no matter what. 21 | result = response.get('result') 22 | if result['total_results'] == 0: 23 | result['prospect'] = [] 24 | elif result['total_results'] == 1: 25 | result['prospect'] = [result['prospect']] 26 | 27 | return result 28 | 29 | def assign_by_email(self, email=None, **kwargs): 30 | """ 31 | Assigns or reassigns the prospect specified by to a specified Pardot user or group. One (and only one) 32 | of the following parameters must be provided to identify the target user or group: , , or 33 | . Returns an updated version of the prospect. 34 | """ 35 | response = self._post(path='/do/assign/email/{email}'.format(email=email), params=kwargs) 36 | return response 37 | 38 | def assign_by_id(self, id=None, **kwargs): 39 | """ 40 | Assigns or reassigns the prospect specified by to a specified Pardot user or group. One (and only one) of 41 | the following parameters must be provided to identify the target user or group: , , or 42 | . Returns an updated version of the prospect. 43 | """ 44 | response = self._post(path='/do/assign/id/{id}'.format(id=id), params=kwargs) 45 | return response 46 | 47 | def unassign_by_email(self, email=None, **kwargs): 48 | """Unassigns the prospect specified by . Returns an updated version of the prospect.""" 49 | response = self._post(path='/do/unassign/email/{email}'.format(email=email), params=kwargs) 50 | return response 51 | 52 | def unassign_by_id(self, id=None, **kwargs): 53 | """Unassigns the prospect specified by . Returns an updated version of the prospect.""" 54 | response = self._post(path='/do/unassign/id/{id}'.format(id=id), params=kwargs) 55 | return response 56 | 57 | def create_by_email(self, email=None, **kwargs): 58 | """ 59 | Creates a new prospect using the specified data. must be a unique email address. Returns the new prospect. 60 | """ 61 | if not email: 62 | raise PardotAPIArgumentError('email is required to create a prospect.') 63 | response = self._post(path='/do/create/email/{email}'.format(email=email), params=kwargs) 64 | return response 65 | 66 | def read_by_email(self, email=None, **kwargs): 67 | """ 68 | Returns data for the prospect specified by , including campaign assignment, profile criteria 69 | matching statuses, associated visitor activities, email list subscriptions, and custom field data. 70 | is the email address of the target prospect. 71 | """ 72 | if not email: 73 | raise PardotAPIArgumentError('email is required to read a prospect.') 74 | response = self._post(path='/do/read/email/{email}'.format(email=email), params=kwargs) 75 | return response 76 | 77 | def read_by_id(self, id=None, **kwargs): 78 | """ 79 | Returns data for the prospect specified by , including campaign assignment, profile criteria 80 | matching statuses, associated visitor activities, email list subscriptions, and custom field data. 81 | is the Pardot ID of the target prospect. 82 | """ 83 | if not id: 84 | raise PardotAPIArgumentError('id is required to read a prospect.') 85 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 86 | return response 87 | 88 | def update_by_email(self, email=None, **kwargs): 89 | """ 90 | Updates the provided data for a prospect specified by . is the email address of the 91 | prospect. Fields that are not updated by the request remain unchanged. 92 | """ 93 | if not email: 94 | raise PardotAPIArgumentError('email is required to update a prospect.') 95 | response = self._post(path='/do/update/email/{email}'.format(email=email), params=kwargs) 96 | return response 97 | 98 | def update_by_id(self, id=None, **kwargs): 99 | """ 100 | Updates the provided data for a prospect specified by . is the Pardot ID of the prospect. 101 | Fields that are not updated by the request remain unchanged. 102 | """ 103 | if not id: 104 | raise PardotAPIArgumentError('id is required to update a prospect.') 105 | response = self._post(path='/do/update/id/{id}'.format(id=id), params=kwargs) 106 | return response 107 | 108 | def upsert_by_email(self, email=None, **kwargs): 109 | """ 110 | Updates the provided data for the prospect specified by . If a prospect with the provided email address 111 | does not yet exist, a new prospect is created using the value. Fields that are not updated by the 112 | request remain unchanged. 113 | """ 114 | if not email: 115 | raise PardotAPIArgumentError('email is required to upsert a prospect.') 116 | response = self._post(path='/do/upsert/email/{email}'.format(email=email), params=kwargs) 117 | return response 118 | 119 | def upsert_by_id(self, id=None, **kwargs): 120 | """ 121 | Updates the provided data for the prospect specified by . If an value is provided, it is used to 122 | update the prospect's email address. If a prospect with the provided ID is not found, Pardot searches for a 123 | prospect identified by . If a prospect with the provided email address does not yet exist, a new 124 | prospect is created using value. Fields that are not updated by the request remain unchanged. 125 | """ 126 | if not id: 127 | raise PardotAPIArgumentError('id is required to upsert a prospect.') 128 | response = self._post(path='/do/upsert/id/{id}'.format(id=id), params=kwargs) 129 | return response 130 | 131 | def delete_by_email(self, email=None, **kwargs): 132 | """Deletes the prospect specified by . Returns True if operation was successful.""" 133 | if not email: 134 | raise PardotAPIArgumentError('email is required to delete a prospect.') 135 | response = self._post(path='/do/delete/email/{email}'.format(email=email), params=kwargs) 136 | if response == 204: 137 | return True 138 | return False 139 | 140 | def delete_by_id(self, id=None, **kwargs): 141 | """Deletes the prospect specified by . Returns True if operation was successful.""" 142 | if not id: 143 | raise PardotAPIArgumentError('id is required to delete a prospect.') 144 | response = self._post(path='/do/delete/id/{id}'.format(id=id), params=kwargs) 145 | if response == 204: 146 | return True 147 | return False 148 | 149 | def update_field_by_id(self, id=None, field_name=None, field_value=None): 150 | """Updates the provided field for the prospect specified by . Returns the updated prospect.""" 151 | response = self.update_by_id(id=id, **{field_name: field_value}) 152 | return response 153 | 154 | def update_field_by_email(self, email=None, field_name=None, field_value=None): 155 | """Updates the provided field for the prospect specified by . Returns the updated prospect.""" 156 | response = self.update_by_email(email=email, **{field_name: field_value}) 157 | return response 158 | 159 | def read_field_by_email(self, email=None, field_name=None): 160 | """Returns the value of the provided field for the prospect specified by .""" 161 | response = self.read_by_email(email=email) 162 | return response.get('prospect').get(field_name) 163 | 164 | def read_field_by_id(self, id=None, field_name=None): 165 | """Returns the value of the provided field for the prospect specified by .""" 166 | response = self.read_by_id(id=id) 167 | return response.get('prospect').get(field_name) 168 | 169 | def add_to_list(self, prospect_id=None, list_id=None): 170 | """Adds the prospect specified by to the list specified by .""" 171 | params = {'prospect_id': prospect_id, 'list_id': list_id} 172 | response = self._post(object_name='listMembership', path='/do/create', params=params) 173 | return response 174 | 175 | def _get(self, object_name='prospect', path=None, params=None): 176 | """GET requests for the Prospect object.""" 177 | if params is None: 178 | params = {} 179 | response = self.client.get(object_name=object_name, path=path, params=params) 180 | return response 181 | 182 | def _post(self, object_name='prospect', path=None, params=None): 183 | """POST requests for the Prospect object.""" 184 | if params is None: 185 | params = {} 186 | response = self.client.post(object_name=object_name, path=path, params=params) 187 | return response 188 | -------------------------------------------------------------------------------- /pypardot/objects/tests/.gitignore: -------------------------------------------------------------------------------- 1 | config.py 2 | -------------------------------------------------------------------------------- /pypardot/objects/tests/README.md: -------------------------------------------------------------------------------- 1 | # Integration Testing 2 | 3 | Copy config.py.example to config.py and fill in the details. 4 | 5 | Running the tests will create and delete objects in the account, so make sure to use a testing account. Pardot will set up a training account for testing purposes if asked. 6 | -------------------------------------------------------------------------------- /pypardot/objects/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joshgeller/PyPardot/349dde1fad561f32a425324005c4f2a0c4a23d9b/pypardot/objects/tests/__init__.py -------------------------------------------------------------------------------- /pypardot/objects/tests/config.py.example: -------------------------------------------------------------------------------- 1 | PARDOT_USER = 'pardot_account_email@example.com' 2 | PARDOT_PASSWORD = 'The Sooper Secret Password 99' 3 | PARDOT_USER_KEY = 'Pardot user key for the user' 4 | -------------------------------------------------------------------------------- /pypardot/objects/tests/test_prospects.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | from pypardot.client import PardotAPI 4 | from pypardot.errors import PardotAPIArgumentError, PardotAPIError 5 | 6 | try: 7 | from pypardot.objects.tests.config import * 8 | CONFIG_EXISTS = True 9 | except SystemError as e: 10 | CONFIG_EXISTS = False 11 | 12 | 13 | @unittest.skipUnless(CONFIG_EXISTS, 'Requires Pardot configuration in config.py') 14 | class TestProspects(unittest.TestCase): 15 | def setUp(self): 16 | self.pardot = PardotAPI(email=PARDOT_USER, password=PARDOT_PASSWORD, user_key=PARDOT_USER_KEY) 17 | self.pardot.authenticate() 18 | 19 | self.email_address = 'parrot@harbles.com' 20 | self.first_name = 'Pickles' 21 | self.last_name = 'Zardnif' 22 | 23 | # Make sure there isn't an existing prospect in the test account. 24 | try: 25 | self.pardot.prospects.delete_by_email(email=self.email_address) 26 | except PardotAPIError as e: 27 | # Error code 4 is raised if the prospect doesn't exist. 28 | if e.err_code != 4: 29 | raise e 30 | 31 | def tearDown(self): 32 | try: 33 | self.pardot.prospects.delete_by_email(email=self.email_address) 34 | except PardotAPIError as e: 35 | # Error code 4 is raised if the prospect doesn't exist. 36 | if e.err_code != 4: 37 | raise e 38 | 39 | def _check_prospect(self, prospect): 40 | self.assertEquals(self.email_address, prospect['email']) 41 | self.assertEquals(self.first_name, prospect['first_name']) 42 | self.assertEquals(self.last_name, prospect['last_name']) 43 | 44 | def test_create_and_read(self): 45 | with self.assertRaises(PardotAPIArgumentError): 46 | results = self.pardot.prospects.create_by_email(first_name=self.first_name, last_name=self.last_name) 47 | 48 | results = self.pardot.prospects.create_by_email(email=self.email_address, first_name=self.first_name, last_name=self.last_name) 49 | 50 | prospect = results['prospect'] 51 | self._check_prospect(prospect) 52 | 53 | with self.assertRaises(PardotAPIArgumentError): 54 | results = self.pardot.prospects.read_by_id(email='test@test.com') 55 | 56 | results = self.pardot.prospects.read_by_id(id=prospect['id']) 57 | self._check_prospect(results['prospect']) 58 | 59 | with self.assertRaises(PardotAPIArgumentError): 60 | results = self.pardot.prospects.read_by_email(id='test') 61 | 62 | results = self.pardot.prospects.read_by_email(email=prospect['email']) 63 | self._check_prospect(results['prospect']) 64 | 65 | def test_update(self): 66 | results = self.pardot.prospects.create_by_email(email=self.email_address, first_name=self.first_name, last_name='McGee') 67 | 68 | prospect = results['prospect'] 69 | self.assertEquals('McGee', prospect['last_name']) 70 | 71 | with self.assertRaises(PardotAPIArgumentError): 72 | self.pardot.prospects.update_by_email(id=prospect['id'], last_name='Ferdle') 73 | 74 | self.pardot.prospects.update_by_email(email=self.email_address, last_name='Ferdle') 75 | 76 | results = self.pardot.prospects.read_by_id(prospect['id']) 77 | self.assertEquals('Ferdle', results['prospect']['last_name']) 78 | 79 | with self.assertRaises(PardotAPIArgumentError): 80 | self.pardot.prospects.update_by_id(email=self.email_address, last_name='Ferdle') 81 | 82 | self.pardot.prospects.update_by_id(id=prospect['id'], last_name='Klampett') 83 | 84 | results = self.pardot.prospects.read_by_id(prospect['id']) 85 | self.assertEquals('Klampett', results['prospect']['last_name']) 86 | 87 | def test_upsert(self): 88 | with self.assertRaises(PardotAPIArgumentError): 89 | results = self.pardot.prospects.upsert_by_email(first_name=self.first_name, last_name=self.last_name) 90 | 91 | results = self.pardot.prospects.upsert_by_email(email=self.email_address, first_name=self.first_name, last_name=self.last_name) 92 | 93 | prospect = results['prospect'] 94 | self._check_prospect(prospect) 95 | 96 | with self.assertRaises(PardotAPIArgumentError): 97 | self.pardot.prospects.upsert_by_id(email=prospect['id'], last_name='Ferdle') 98 | 99 | self.pardot.prospects.upsert_by_email(email=self.email_address, first_name=self.first_name, last_name='Ferdle') 100 | 101 | results = self.pardot.prospects.read_by_email(prospect['email']) 102 | self.assertEquals('Ferdle', results['prospect']['last_name']) 103 | self.assertEquals(prospect['id'], results['prospect']['id']) 104 | 105 | def test_delete(self): 106 | results = self.pardot.prospects.create_by_email(email=self.email_address, first_name=self.first_name, last_name=self.last_name) 107 | prospect = results['prospect'] 108 | 109 | with self.assertRaises(PardotAPIArgumentError): 110 | self.pardot.prospects.delete_by_email(id=prospect['id']) 111 | 112 | with self.assertRaises(PardotAPIArgumentError): 113 | self.pardot.prospects.delete_by_id(email=prospect['email']) 114 | 115 | results = self.pardot.prospects.read_by_id(prospect['id']) 116 | self.pardot.prospects.delete_by_id(id=prospect['id']) 117 | with self.assertRaises(PardotAPIError): 118 | results = self.pardot.prospects.read_by_id(prospect['id']) 119 | -------------------------------------------------------------------------------- /pypardot/objects/users.py: -------------------------------------------------------------------------------- 1 | class Users(object): 2 | """ 3 | A class to query and use Pardot users. 4 | User field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#user 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the users matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/users/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['users'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['user'] = [] 21 | elif result['total_results'] == 1: 22 | result['user'] = [result['user']] 23 | 24 | return result 25 | 26 | def read_by_id(self, id=None, **kwargs): 27 | """ 28 | Returns the data for the user specified by . is the Pardot ID of the target user.""" 29 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 30 | return response 31 | 32 | def read_by_email(self, email=None, **kwargs): 33 | """ 34 | Returns the data for the user specified by . is the email address of the target user.""" 35 | response = self._post(path='/do/read/email/{email}'.format(email=email), params=kwargs) 36 | return response 37 | 38 | def _get(self, object_name='user', path=None, params=None): 39 | """GET requests for the User object.""" 40 | if params is None: 41 | params = {} 42 | response = self.client.get(object_name=object_name, path=path, params=params) 43 | return response 44 | 45 | def _post(self, object_name='user', path=None, params=None): 46 | """POST requests for the User object.""" 47 | if params is None: 48 | params = {} 49 | response = self.client.post(object_name=object_name, path=path, params=params) 50 | return response 51 | -------------------------------------------------------------------------------- /pypardot/objects/visitoractivities.py: -------------------------------------------------------------------------------- 1 | class VisitorActivities(object): 2 | """ 3 | A class to query and use Pardot visitor activities. 4 | Visitor Activity field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#visitor-activity 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the visitor activities matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/visitor-activities/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['visitor_activity'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['visitor_activity'] = [] 21 | elif result['total_results'] == 1: 22 | result['visitor_activity'] = [result['visitor_activity']] 23 | 24 | return result 25 | 26 | def read(self, id=None, **kwargs): 27 | """ 28 | Returns the data for the visitor activity specified by . is the Pardot ID for the target visitor activity. 29 | """ 30 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 31 | return response 32 | 33 | def _get(self, object_name='visitorActivity', path=None, params=None): 34 | """GET requests for the Visitor Activity object.""" 35 | if params is None: 36 | params = {} 37 | response = self.client.get(object_name=object_name, path=path, params=params) 38 | return response 39 | 40 | def _post(self, object_name='visitorActivity', path=None, params=None): 41 | """POST requests for the Visitor Activity object.""" 42 | if params is None: 43 | params = {} 44 | response = self.client.post(object_name=object_name, path=path, params=params) 45 | return response 46 | -------------------------------------------------------------------------------- /pypardot/objects/visitors.py: -------------------------------------------------------------------------------- 1 | class Visitors(object): 2 | """ 3 | A class to query and use Pardot visitors. 4 | Visitor field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#visitor 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query(self, **kwargs): 11 | """ 12 | Returns the visitors matching the specified criteria parameters. 13 | Supported search criteria: http://developer.pardot.com/kb/api-version-3/visitors/#supported-search-criteria 14 | """ 15 | response = self._get(path='/do/query', params=kwargs) 16 | 17 | # Ensure result['visitor'] is a list, no matter what. 18 | result = response.get('result') 19 | if result['total_results'] == 0: 20 | result['visitor'] = [] 21 | elif result['total_results'] == 1: 22 | result['visitor'] = [result['visitor']] 23 | 24 | return result 25 | 26 | def assign(self, id=None, **kwargs): 27 | """ 28 | Assigns or reassigns the visitor specified by to a specified prospect. One (and only one) of the following 29 | parameters must be provided to identify the target prospect: or . Returns an 30 | updated version of the visitor. 31 | """ 32 | response = self._post(path='/do/assign/id/{id}'.format(id=id), params=kwargs) 33 | return response 34 | 35 | def read(self, id=None, **kwargs): 36 | """ 37 | Returns the data for the visitor specified by , including associated visitor activities, identified 38 | company data, and visitor referrers. is the Pardot ID for the target visitor. 39 | """ 40 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 41 | return response 42 | 43 | def _get(self, object_name='visitor', path=None, params=None): 44 | """GET requests for the Visitor object.""" 45 | if params is None: 46 | params = {} 47 | response = self.client.get(object_name=object_name, path=path, params=params) 48 | return response 49 | 50 | def _post(self, object_name='visitor', path=None, params=None): 51 | """POST requests for the Visitor object.""" 52 | if params is None: 53 | params = {} 54 | response = self.client.post(object_name=object_name, path=path, params=params) 55 | return response 56 | -------------------------------------------------------------------------------- /pypardot/objects/visits.py: -------------------------------------------------------------------------------- 1 | class Visits(object): 2 | """ 3 | A class to query and use Pardot visits. 4 | Visit field reference: http://developer.pardot.com/kb/api-version-3/object-field-references/#visit 5 | """ 6 | 7 | def __init__(self, client): 8 | self.client = client 9 | 10 | def query_by_ids(self, ids=None, **kwargs): 11 | """Returns the visits matching the given . The should be comma separated integers (no spaces).""" 12 | kwargs['ids'] = ids.replace(' ', '') 13 | response = self._get(path='/do/query', params=kwargs) 14 | 15 | # Ensure result['visit'] is a list, no matter what. 16 | result = response.get('result') 17 | if result['total_results'] == 0: 18 | result['visit'] = [] 19 | elif result['total_results'] == 1: 20 | result['visit'] = [result['visit']] 21 | 22 | return result 23 | 24 | def query_by_visitor_ids(self, visitor_ids=None, **kwargs): 25 | """ 26 | Returns the visits matching the given . The should be comma separated integers 27 | (no spaces). 28 | """ 29 | kwargs['visitor_ids'] = visitor_ids.replace(' ', '') 30 | response = self._get(path='/do/query', params=kwargs) 31 | 32 | # Ensure result['visit'] is a list, no matter what. 33 | result = response.get('result') 34 | if result['total_results'] == 0: 35 | result['visit'] = [] 36 | elif result['total_results'] == 1: 37 | result['visit'] = [result['visit']] 38 | 39 | return result 40 | 41 | def query_by_prospect_ids(self, prospect_ids=None, **kwargs): 42 | """ 43 | Returns the visits matching the given . The should be comma separated integers 44 | (no spaces). 45 | """ 46 | kwargs['prospect_ids'] = prospect_ids.replace(' ', '') 47 | response = self._get(path='/do/query', params=kwargs) 48 | 49 | # Ensure result['visit'] is a list, no matter what. 50 | result = response.get('result') 51 | if result['total_results'] == 0: 52 | result['visit'] = [] 53 | elif result['total_results'] == 1: 54 | result['visit'] = [result['visit']] 55 | 56 | return result 57 | 58 | def read(self, id=None, **kwargs): 59 | """ 60 | Returns the data for the visit specified by . is the Pardot ID of the target visit.""" 61 | response = self._post(path='/do/read/id/{id}'.format(id=id), params=kwargs) 62 | return response 63 | 64 | def _get(self, object_name='visit', path=None, params=None): 65 | """GET requests for the Visit object.""" 66 | if params is None: 67 | params = {} 68 | response = self.client.get(object_name=object_name, path=path, params=params) 69 | return response 70 | 71 | def _post(self, object_name='visit', path=None, params=None): 72 | """POST requests for the Visit object.""" 73 | if params is None: 74 | params = {} 75 | response = self.client.post(object_name=object_name, path=path, params=params) 76 | return response 77 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | 4 | setup( 5 | name="PyPardot", 6 | version="0.1", 7 | author="Josh Geller", 8 | author_email="joshualgeller@gmail.com", 9 | description=("API wrapper for Pardot marketing automation software."), 10 | keywords="pardot", 11 | url="https://github.com/joshgeller/PyPardot", 12 | packages=['pypardot', 'pypardot.objects'], 13 | install_requires=['requests'], 14 | ) 15 | --------------------------------------------------------------------------------