├── README.md └── examples └── basic_integration_example.py /README.md: -------------------------------------------------------------------------------- 1 | # SendCloud API Integration Example 2 | 3 | There are various ways to integrate the SendCloud shipping solution with your own platform. 4 | The [API documentation][sc_api_docs] gives a complete overview of the possibilities. 5 | This repository should provide you clear and understandable examples on how you can integrate SendCloud. 6 | 7 | ## Setting up the API credentials 8 | 9 | Before you can interact with the API it is essential that you setup API credentials. 10 | Make sure that you are signed up by creating an account: 11 | https://panel.sendcloud.sc/accounts/signup/ 12 | 13 | Once you have set up an account we advice you to setup your payment contract: 14 | https://panel.sendcloud.sc/#/settings/financial/payments/direct-debit 15 | Registering your payment credentials is necessary to ensure you can make use of the full capabilities of the API. 16 | 17 | Once done you can create API keys: 18 | https://panel.sendcloud.sc/#/settings/integrations/api/add 19 | Make sure that you give it a recognizable name. Ensure that you press the save button. 20 | 21 | Once saved you should see the Public key and Secret key. Make sure you save them somewhere safely. 22 | You are going to need those credentials to authenticate with the API. 23 | 24 | ## Examples 25 | Below you can find the links to Python files which show how to use the API. 26 | The scripts are written in Python 3 and require [Requests][requests_docs] to be installed. 27 | You can easily inspect and learn more about the code. 28 | 29 | Running the scripts to interact with the API simple. Take the following create parcel example: 30 | 31 | ``` 32 | python3 examples/basic_integration_example.py --action create --public XXXXX --secret XXXXX --partner_id YYYYY 33 | ``` 34 | 35 | You can change _action_ from create to one of the options which you can find in the section below. 36 | Make sure you replace _XXXXX_ by your public and secret key. 37 | You can replace _YYYYY_ by the partner id. 38 | Also can drop the partner_id if you don't have one as it is optional. 39 | At last it is recommended to inspect the code before running it. 40 | 41 | ### Actions 42 | 43 | + [basic_integration_example.py](examples/basic_integration_example.py) 44 | + __create:__ Create a shipment in SendCloud to be processed. 45 | + __cancel__ Cancel a shipment in SendCloud before or after processing. 46 | + _NOTE:_ This action asks for input while executing! 47 | 48 | ### Final note about testing 49 | 50 | SendCloud offers no sandbox. If you are testing please notice that there are free and paid shipping options in your account. 51 | There is a unstamped label option in the platform which is free and which is recommended for testing. 52 | 53 | Once your integration is working you can check with paid shipping methods, but make sure that you cancel them before the cancellation 54 | deadline otherwise you have to pay for this label on the next invoice. 55 | [More info about cancelling a shipment.][cancel_shipment] 56 | 57 | 58 | [sc_api_docs]: https://docs.sendcloud.sc/api/v2/index.html 59 | [requests_docs]: http://docs.python-requests.org/en/master/ 60 | [cancel_shipment]: https://support.sendcloud.com/english/settings/how-do-i-cancel-my-shipment 61 | -------------------------------------------------------------------------------- /examples/basic_integration_example.py: -------------------------------------------------------------------------------- 1 | #! /bin/env python3 2 | import requests 3 | import argparse 4 | import json 5 | 6 | 7 | def create_parcel(public_key, secret_key, partner_id=None): 8 | # Example data for a minimal implementation. 9 | # Notice that you only need little information 10 | # to get started to be able to process a shipment 11 | # with the SendCloud platform. 12 | 13 | data = { 14 | "parcel": { 15 | "name": "John Doe", 16 | "company_name": "SendCloud", 17 | "address": "Insulindelaan", 18 | "postal_code": "5642CV", 19 | "house_number": "115", 20 | "city": "Eindhoven", 21 | "country": "NL", 22 | "telephone": "+31612345678", 23 | "email": "john.doe@example.com", 24 | "weight": "10.000", # in KG 25 | "order_number": "1234567890", 26 | } 27 | } 28 | 29 | headers = {} 30 | headers['Content-Type'] = 'application/json' 31 | 32 | # Optional, but recommended for partners 33 | # This allows us to identify that your request 34 | # came from your platform. 35 | if partner_id: 36 | headers['Sendcloud-Partner-Id'] = partner_id 37 | 38 | response = requests.post( 39 | headers=headers, 40 | url='https://panel.sendcloud.sc/api/v2/parcels/', 41 | data=json.dumps(data), 42 | auth=(public_key, secret_key,) 43 | ) 44 | 45 | # response.status_code should be HTTP 200, 46 | # if this is not the case. Throw a exception. 47 | response.raise_for_status() 48 | 49 | # Show the response on stdout. 50 | # It may be useful to remember the "parcel id". 51 | # This can be found in the response. 52 | print(response.json()) 53 | 54 | 55 | def cancel_parcel(public_key, secret_key, partner_id=None): 56 | # Very similar to the example above. 57 | headers = {} 58 | headers['Content-Type'] = 'application/json' 59 | if partner_id: 60 | headers['Sendcloud-Partner-Id'] = partner_id 61 | 62 | # Data can be a empty JSON response 63 | data = {} 64 | 65 | # Ask the script user to enter the parcel/shipment id. 66 | parcel_id = input('Enter the ID of the shipment that you want to cancel.') 67 | 68 | # Shipment/parcel id is part of the URL. 69 | base_url = 'https://panel.sendcloud.sc/api/v2/' 70 | url = base_url + 'parcels/{parcel_id}/cancel/'.format( 71 | parcel_id=parcel_id 72 | ) 73 | response = requests.post( 74 | headers=headers, 75 | url=url, 76 | data=json.dumps(data), 77 | auth=(public_key, secret_key,) 78 | ) 79 | 80 | try: 81 | # response.status_code should be HTTP 200, 82 | # if this is not the case. Throw a exception. 83 | response.raise_for_status() 84 | except requests.exceptions.HTTPError as e: 85 | if e.response.status_code not in [ 86 | 200, # Cancelled 87 | 202, # Cancellation queued 88 | 410 # Cancelled before label creation 89 | ]: 90 | raise e 91 | 92 | # Important to check the response as it may be different based on the state 93 | # of the shipment. 94 | print(response.json()) 95 | 96 | 97 | if __name__ == '__main__': 98 | # Parse the command line arguments 99 | parser = argparse.ArgumentParser() 100 | parser.add_argument('--action') 101 | parser.add_argument('--public') 102 | parser.add_argument('--secret') 103 | parser.add_argument('--partner_id') 104 | args = parser.parse_args() 105 | 106 | action = args.action 107 | public_key = args.public 108 | secret_key = args.secret 109 | partner_id = args.partner_id 110 | 111 | # Map arguments to actions 112 | actions = { 113 | 'create': create_parcel, 114 | 'cancel': cancel_parcel 115 | } 116 | 117 | action_func = actions[action] 118 | action_func(public_key, secret_key, partner_id) 119 | --------------------------------------------------------------------------------