The V1 API is officially deprecated as of March 31, 2020.
As of Sep 2020, if you are still using API V1, you are in-fact accessing V2. The V2 API is mostly backwards compatible with the V1 API.
Fulfil REST API Client in Python
- Free software: ISC license
- Documentation: https://fulfil-python-api.readthedocs.org.
- Examples: https://github.com/fulfilio/fulfil-python-api/tree/master/examples.
- Ability to call models
pip install fulfil_clientfromfulfil_clientimportClientclient=Client('<subdomain>', '<api_key>')
Product=client.model('product.product')
# find productssome_products=Product.find()
# find products that have a name similar to iphoneiphones=Product.find(['name', 'ilike', 'iphone'])Contact can have multiple addresses and contact mechanisms i.e. phone, email.
fromfulfil_clientimportClientclient=Client('<subdomain>', '<api_key>')
Contact=client.model('party.party')
Country=client.model('country.country')
Subdivision=client.model('country.subdivision')
country_usa, =Country.find([('code', '=', 'US')])
state_california, =Subdivision.find([('code', '=', 'US-CA')])
# Creating a contact with address and contact mechanismscontact, =Contact.create([{
'name': 'Jon Doe',
'addresses': [('create', [{
'name': 'Jone Doe Apartment',
'street': '9805 Kaiden Grove',
'city': 'New Leland',
'zip': '57726',
'country': country_usa['id'],
'subdivision': state_california['id']
}])],
'contact_mechanisms': [('create', [{
'type': 'phone',
'value': '243243234'
}, {
'email': 'email',
'value': 'hello@jondoe.com'
}])]
}])
printcontact# Searching for a contactcontact, =Contact.find([('name', '=', 'Jon Doe')])
printcontact# Get a contact by IDcontact=Contact.get(contact['id'])
printcontactProducts are grouped by templates, which have common information shared by products a.k.a. variants.
fromdecimalimportDecimal# Creating a Product TemplateTemplate=client.model('product.template')
iphone, =Template.create([{
'name': 'iPhone',
'account_category': True,
}])
# Creating productsProduct=client.model('product.product')
iphone6, =Product.create([{
'template': iphone['id'],
'variant_name': 'iPhone 6',
'code': 'IPHONE-6',
'list_price': Decimal('699'),
'cost_price': Decimal('599'),
}])
# Another variationiphone6s, =Product.create([{
'template': iphone['id'],
'variant_name': 'iPhone 6S',
'code': 'IPHONE-6S',
'list_price': Decimal('899'),
'cost_price': Decimal('699'),
}])contact=Contact.get(contact['id'])
iphone6=Product.get(iphone6['id'])
iphone6s=Product.get(iphone6s['id'])
# Creating a SaleSale=client.model('sale.sale')
sale, =Sale.create([{
'party': contact['id'],
'shipment_address': contact['addresses'][0],
'invoice_address': contact['addresses'][0],
'lines': [('create', [{
'product': iphone6['id'],
'description': iphone6['rec_name'],
'unit': iphone6['default_uom'],
'unit_price': iphone6['list_price'],
'quantity': 3
}, {
'product': iphone6s['id'],
'description': iphone6s['rec_name'],
'unit': iphone6['default_uom'],
'unit_price': iphone6s['list_price'],
'quantity': 1
}])]
}])The report data (including rendering) information can be fetched over the API.
Below is the example code to fetch sales by month report.
report=client.interactive_report('sales_by_month.ireport')
data=report.execute(start_date=date(2017,1,1), end_date=date(2017, 12,1))fromfulfil_clientimportClient, SessionAuthclient=Client('subdomain')
user_id, session=client.login('username', 'password')
client.set_auth(SessionAuth(user_id, session))fromfulfil_clientimportClient, BearerAuthclient=Client('subdomain')
client.set_auth(BearerAuth(bearer_token))Flask example
fromfulfil_client.oauthimportSessionfromfulfil_clientimportClient, BearerAuthSession.setup(CLIENT_ID, CLIENT_SECRET)
fulfil_session=Session('localhost') # Provide subdomain@app.route('/')defindex():
callback_url=url_for('authorized')
if'oauth_token'notinsession:
authorization_url, state=fulfil_session.create_authorization_url(
redirect_uri=callback_url, scope=['user_session']
)
session['oauth_state'] =statereturnredirect(authorization_url)
client=Client('subdomain')
client.set_auth(BearerAuth(session['oauth_token']['access_token']))
Party=client.model('party.party')
returnjsonify(Party.find())
@app.route('/authorized')defauthorized():
"""Callback route to fetch access token from grant code """token=fulfil_session.get_token(code=request.args.get('code'))
session['oauth_token'] =tokenreturnjsonify(oauth_token=token)There is a convenience function that can verify the webhooks originating from Fulfil for you.
fromfulfil_clientimportverify_webhook@app.route('/webhook', methods=['POST'])defwebhook():
data=flask.request.get_data()
verified=verify_webhook(
data,
secret, # This should be saved somewhereflask.request.headers.get('X-Fulfil-Hmac-SHA256')
)
ifnotverified:
abort(401)The libary also provides a mocking function powered by the mock library of python.
For example, if you want to test the function below
defapi_calling_method():
client=fulfil_client.Client('apple', 'apples-api-key')
Product=client.model('product.product')
products=Product.search_read_all([], None, ['id'])
Product.write(
[p['id'] forpinproducts],
{'active': False}
)
returnclientThen the test case can mock the API call
deftest_mock_1():
withMockFulfil('fulfil_client.Client') asmocked_fulfil:
Product=mocked_fulfil.model('product.product')
# Set the return value of the search call without# hitting the server.Product.search_read_all.return_value= [
{'id': 1},
{'id': 2},
{'id': 3},
]
# Call the functionapi_calling_method()
# Now assertProduct.search_read_all.assert_called()
Product.search_read_all.assert_called_with([], None, ['id'])
Product.write.assert_called_with(
[1, 2, 3], {'active': False}
)The Product object returned is a mock.Mock object and supports all of the assertions supported by python Mock objects.
Fulfil.IO Inc.