Package: sendbee-api
Sendbee Python API Client.' '.            __
       .        .   .           (__\_
        .         .         . -{{_(|8)
          ' .  . ' ' .  . '     (__/Table of contentsInstallationInitializationContactsFetch contactsSubscribe contactUpdate contactContact TagsFetch contact tagsCreate contact tagUpdate contact tagDelete contact tagContact FieldsFetch contact fieldsCreate contact fieldUpdate contact fieldDelete contact fieldConversationsFetch conversationsFetch conversation messagesFetch message templatesSend template messageSend messageTeamsFetch teamsFetch team membersAutomationManaging chatbot (automated responses) status settingsGet chatbot (automated responses) statusMicsPaginationAPI Rate LimitRaw responseException handlingAuthenticate webhook requestWarningsDebuggingOfficial DocumentationInstallation>pipinstallsendbee-apiInitializationfromsendbee_apiimportSendbeeApiapi=SendbeeApi('__your_api_key_here__','__your_secret_key_here__')ContactsFetch contactscontacts=api.contacts([tags=['...',...]],[status='subscribed|unsubscribed'],[search_query='...'],[page=...],[limit=...])forcontactincontacts:contact.idcontact.statuscontact.foldercontact.created_atcontact.namecontact.phonefortagincontact.tags:tag.idtag.namefornoteincontact.notes:note.valueforcontact_fieldincontact.contact_fields:contact_field.keycontact_field.valueSubscribe contactcontact=api.subscribe_contact(phone='+...',# this is mandatory the most important information# about the subscribing contact[tags=['...',...]],# tag new contact# if tag doesn't exist, it will be created[name='...'],[notes=[...]],# write notes about your new subscriber[contact_fields={'__field_name__':'__field_value__',...}],# fill contact fields with your data (value part)# contact fields must be pre-created in Sendbee Dashboard# any non-existent field will be ignored[block_notifications=[True|False]],# prevent sending browser push notification and email# notification to agents, when new contact subscribes# (default is True)[block_automation=[True|False]]# prevent sending automated template messages to newly# subscribed contact (if any is set in Sendbee Dashboard)# (default is True))contact.idcontact.statuscontact.foldercontact.created_atcontact.namecontact.phonefortagincontact.tags:tag.idtag.namefornoteincontact.notes:note.valueforcontact_fieldincontact.contact_fields:contact_field.keycontact_field.valueUpdate contactcontact=api.update_contact(id='...',# contact is identified with ID[phone='+...'],# this is the most important information# about the subscribing contact[tags=['...',...]],# tag new contact# if tag doesn't exist, it will be created[name='...'],[notes=[...]],# write notes about your new subscriber# if there are notes already saved for this contact# new notes will be appended[contact_fields={'__field_name__':'__field_value__',...}],# fill contact fields with your data (value part)# contact fields must be pre-created in Sendbee Dashboard# any non-existent field will be ignored# if there are fields already filled with data for this contact# it will be overwritten with new data)contact.idcontact.statuscontact.foldercontact.created_atcontact.namecontact.phonefortagincontact.tags:tag.idtag.namefornoteincontact.notes:note.valueforcontact_fieldincontact.contact_fields:contact_field.keycontact_field.valueContact tagsFetch contact tagstags=api.tags([name='...'],[page=...],[limit=...])fortagintags:tag.idtag.nameCreate contact tagtag=api.create_tag(name='...')tag.idtag.nameUpdate contact tagtag=api.update_tag(id='...',name='...')tag.idtag.nameDelete contact tagresponse=api.delete_tag(id='...')response.messageContact fieldsFetch contact fieldscontact_fields=api.contact_fields([search_query='...'],[page=...],[limit=...])forcontact_fieldincontact_fields:contact_field.namecontact_field.typeifcontact_field.type=='list':contact_field.optionsCreate contact fieldIf a contact field type is a list, then you need to send a list options.List options is a list of option names:['option1', 'option2', ...]contact_field=api.create_contact_field(name='...',type='text|number|list|date|boolean',[options=['...'....]]# if contact field type is list)contact_field.idcontact_field.namecontact_field.typeifcontact_field.type=='list':contact_field.optionsUpdate contact fieldIf a contact field type is a list, then you need to send a list options.List options is a list of option names:['option1', 'option2', ...]contact_field=api.update_contact_field(id='...',[name='...'],[type='text|number|list|date|boolean'],[options=['...'....]]# if contact field type is list)contact_field.idcontact_field.namecontact_field.typeifcontact_field.type=='list':contact_field.optionsDelete contact fieldresponse=api.delete_contact_field(id='...')response.messageConversationsFetch conversationsconversations=api.conversations([folder='open|done|spam|notified'],[search_query='...'],[page=...],[limit=...],[date_from=__timestamp__],[date_to=__timestamp__])forconversationinconversations:conversation.idconversation.folderconversation.chatbot_activeconversation.platformconversation.created_atconversation.contact.idconversation.contact.nameconversation.contact.phoneconversation.last_message.directionconversation.last_message.statusconversation.last_message.inbound_sent_atconversation.last_message.outbound_sent_atFetch conversation messagesmessages=api.messages(conversation_id='...',[page=...])formessageinmessages:message.bodymessage.media_typemessage.media_urlmessage.statusmessage.directionmessage.sent_atFetch message templatesMessage templates must first be sent for approval.Therefor every message template could have following status:pending,approved,rejectedIf message template comms withrejectedstatus, it also comes withrejected_reason.templates=api.message_templates([status="pending|approved|rejected"],[search_query='...'],[page=...],[limit=...])fortemplateintemplates:template.idtemplate.texttemplate.buttons# available for all Sendbee users onboarded after 11th of December 2020template.button_tags# available for all Sendbee users onboarded after 11th of December 2020template.tagstemplate.keywordtemplate.languagetemplate.statustemplate.rejected_reasonSend template messageMessage template can be purely textual or textual with attachment.If it is with attachment, that means you can send image, video or document URL together with text.When you get a list of message templates, every template in that list hasattachmentfield with it's value.Attachment field value defines which type of attachment can be sent with message template:ValueDescriptionimageMessage template can be sent with image URL: JPG/JPEG, PNGvideoMessage template can be sent with video URL: MP4, 3GPPdocumentMessage template can be sent with document URL: PDF, DOC, DOCX, PPT, PPTX, XLS, XLSXnullMessage template does not support attachment URLresponse=api.send_template_message(phone='+...',template_keyword='...',# every pre-created and approved message template# is identified with a keywordlanguage='...',# language keyword# example: en (for english)tags={'__tag_key__':'__tag_value__',...},# tags for template messages are parts of the message that need# to be filled with your custom data# example:# template message: "Welcome {{1}}! How can we help you?"# tags: {"1": "John"}# Learn more: https://developer.sendbee.io/#send-message-templatebutton_tags={'__tag_key__':'__tag_value__',...}# tags for call-to-action button with dynamic URL suffix that need# to be filled with your custom data# example:# template message: https://example.com/{{1}}# tags: {"1": "page/123"}[prevent_bot_off=True|False],# if set to True, will prevent turning-off chatbot for the conversation# default system behaviour is that chatbot is turned-off[attachment='http...'])response.statusresponse.conversation_idresponse.message_id# save this id, and when you get sent message status requests on# your webhook, you'll get this same id to identify the conversationSend messageYou can send either text message or media message.For media message, following formats are supported:CategoryFormatsAudioAAC, M4A, AMR, MP3, OGG OPUSVideoMP4, 3GPPImageJPG/JPEG, PNGDocumentPDF, DOC, DOCX, PPT, PPTX, XLS, XLSXresponse=api.send_message(phone='+...',[text='...'],# any kind of message text[media_url='...'],# URL to a media.# you need to upload it your self and send us the URL[prevent_bot_off=True|False]# if set to True, will prevent turning-off chatbot for the conversation# default system behaviour is that chatbot is turned-off)response.statusresponse.conversation_idresponse.message_id# save this id, and when you get sent message status requests on# your webhook, you'll get this same id to identify the conversationTeamsFetch teamsteams=api.teams([member_id='...'])forteaminteams:team.idteam.nameformemberinteam.members:member.idmember.namemember.rolemember.onlinemember.availableFetch team membersmembers=api.members([team_id='...'])formemberinmembers:member.idmember.namemember.rolemember.onlinemember.availableforteaminmember.teams:team.idteam.nameAutomationManaging chatbot (automated responses) status settingsEvery contact is linked to a conversation with an agent.Conversation could be handled by an agent or a chatbot (automated responses).Every time a message has been sent to a contact by an agent or using the API,
the chatbot will automatically be turned off for that conversation -
except when you set 'prevent_bot_off' to true via API call (seeSend message).Use the example below to change the chatbot status based on your use case.api.chatbot_activity(conversation_id='...',active=True|False)Get chatbot (automated responses) statusYou can also check if chatbot is turned on or off for a conversation.response=api.chatbot_activity_status(conversation_id='...')response.conversation_idresponse.chatbot_active# True/FalseMiscPaginationYou can paginate on every endpoint/method where a list of something is fetching.Wherever you see[page=...]it means you can paginate likepage=2,page=3, etc. The best way to do that is to use.next_page()method.There are two ways to detect that pagination ended, usingPaginationExceptionand using.has_next()method.Paginate using .next_page() and PaginationException:fromsendbee_apiimportPaginationExceptionmessages=api.messages(conversation_id='...')# first pagewhileTrue:try:messages=api.messages(conversation_id='...',page=messages.next_page())exceptPaginationExceptionase:breakPaginate using .next_page() and .has_next() methods:messages=api.messages(conversation_id='...')# first pagewhileTrue:ifnotmessages.has_next():breakmessages=api.messages(conversation_id='...',page=messages.next_page())API Rate LimitA rate limit is the number of API calls a business number can make
within a given time period. If this limit is exceeded,
API requests are throttled, and will fail with 429 error response.No matter how many API keys you make in your Sendbee account,
rate limit will always be counted within a business number.fromsendbee_apiimportSendbeeRequestApiExceptiontry:api.rate_limit_request_test()exceptSendbeeRequestApiExceptionasex:retry_after=ex.response.headers.get('Retry-After')Raw responseIf you prefer to deal with the raw server response, response string is available under raw_datafromsendbee_apiimportSendbeeApiapi=SendbeeApi('__your_api_key_here__','__your_secret_key_here__')response=api.contacts()print(response.raw_data)Exception handlingEvery time something is not as it should be, like parameter is missing, parameter value is invalid, authentication fails, etc, API returns a http status code accordingly and an error message.By using this client library, an error message is detected and taken, and an exception is raised, so you can handle it like this:fromsendbee_apiimportSendbeeRequestApiExceptiontry:api.send_template_message(...)exceptSendbeeRequestApiExceptionase:# handle exceptionAuthenticate webhook requestAfter activating your webhook URL in Sendbee Dashboard, we will start sending requests on that URL depending on which webhook type is linked with that webhook URL.Every request that we make will have authorization token in header, like this:{
    ...
    'X-Authorization': '__auth_token_here__',
    ...
}To authenticate requests that we make to your webhook URL, take this token from request header and check it using Sendbee API Client:fromsendbee_apiimportSendbeeApiapi=SendbeeApi('__your_api_key_here__','__your_secret_key_here__')token='...'# taken from the request headerifnotapi.auth.check_auth_token(token):# error! authentication failed!WarningsSometimes APi returns a worning so you could be warned about something.The waning is displayed in standard output:DebuggingThis library has it's own internal debugging tool.By default it is disabled, and to enable it, pass thedebugparameter:fromsendbee_apiimportSendbeeApiapi=SendbeeApi('__your_api_key_here__','__your_secret_key_here__',debug=True)Once you enabled the internal debug tool, every request to API will output various request and response data in standard output: