Skip to main content

Plando

Plando is an Israeli CRM for managing contacts, leads, activities, and documents.

Official Plando API docs (for deeper reference):


CRM config (crmConfig)

FieldRequiredDefaultUse
tokenYesAPI access key (access_key). Required for all operations.
chatYesPlando chat ID. Required for newOpportunity.
customerIdNoCustomer Texter project IDAllowes overriding the current project ID with something else. Used in openTicket/closeTicket — sets formal_whatsapp_url to {customerId}.texterchat.com.
defaultEmailNoFallback agent email for openTicket/closeTicket when no agent is assigned to the chat.
closeTicketMaxMessagesCountNo30Max number of messages to include in the transcript pushed by openTicket/closeTicket.
failOnMultipleContactsNofalseIf true, getCustomerDetails returns on_failure when the phone matches more than one contact.
statusFieldNoidPlando contact field name whose value is mapped to crmData.status.
idFieldNoidPlando contact field name whose value is mapped to crmData.id.
attrFieldsNoComma-separated contact attribute field names to request (e.g. "category_1,category_2"). Merged with pullContactByField, idField, statusField into the API's attr param.
pullContactByFieldNo{ "fieldName": "expectedValue" }. When set, selects the first contact where fieldName === expectedValue. If expectedValue is empty, selects the first contact where fieldName is non-empty. Falls back to the first contact if none match.

Adapter functions

getCustomerDetails

Looks up a contact in Plando by phone (or other search options).

When it runs: At the start of the flow to identify whether the sender is a known contact before routing, and whenever a chat is opened in the Texter UI.

Basic

  plando_lookup:
type: func
func_type: crm
func_id: getCustomerDetails
on_complete: known_customer
on_failure: unknown_customer

All YAML params (except phoneNumber) are forwarded as-is into the API's search_options object.

ParamNotes
phoneNumberPhone to look up. Defaults to the chat's formatted channel phone.
contact_idSearch by Plando contact ID instead of phone.
contact_mailSearch by email.
contact_p_idSearch by personal / national ID.
contact_nameSearch by full name. Per Plando docs: only relevant when contact_mail is also present.
from_contact_idReturn contacts starting from this Plando contact ID.
created_atSearch contacts created from this datetime ("YYYY-MM-DD HH:mm").
created_at_toUpper bound for created_at range.
updated_atSearch contacts updated from this datetime ("YYYY-MM-DD HH:mm").
updated_at_toUpper bound for updated_at range.
customer_statusFilter by status. Possible values: 0 = Potential customer, 1 = Customer, 2 = Not interested. Multiple values comma-separated. Only relevant with updated_at or created_at.
extra_paramsObject { field_name: value } for filtering by a specific contact field. Only relevant with updated_at or created_at.
input_idSet to 1 to return categories and tags by ID instead of name. Default 0.
extra_objects_idsComma-separated type IDs — retrieves extra linked object details.
(attr)Not a YAML param. Always set by the adapter from crmConfig.attrFields, idField, statusField, and pullContactByField.

Result: On success, crmData is populated with:

crmData fieldSource
(all contact fields)All raw Plando contact fields spread directly (e.g. first_name, last_name, category_1, category_30, etc.)
contact_idcontact.id
namefirst_name + ' ' + last_name
statusValue of crmConfig.statusField on the contact (default field: id)
idValue of crmConfig.idField on the contact (default field: id)
phonePhone used for lookup
deepLinkhttps://plando.co.il/contacts/show/{contact.id}

Returns on_failure if: token/chat missing from config, phone is unavailable, API returns an error, no contact is found, or failOnMultipleContacts: true and multiple contacts match.

Advanced — lookup by custom phone

  plando_lookup_by_collected_phone:
type: func
func_type: crm
func_id: getCustomerDetails
params:
phoneNumber: "%state:node.collect_phone.text%"
on_complete: known_customer
on_failure: unknown_customer
Requesting custom attribute fields

Use crmConfig.attrFields to specify which Plando category/attribute fields should be fetched (comma-separated). These are then accessible on crmData under their Plando field name.

attrFields: "category_1,category_9,category_17,category_30,invoices_archive,last_open_invoice,signed_form"

Access them in YAML as %chat:crmData.category_30%, %chat:crmData.last_open_invoice%, etc.


newOpportunity

Creates a new contact/lead in Plando. Can also update an existing contact when updateContact is set.

Basic

  plando_new_lead:
type: func
func_type: crm
func_id: newOpportunity
on_complete: lead_created
on_failure: lead_failed

The adapter always sends chat (from crmConfig.chat), access_key (from crmConfig.token), and no_redirect: 1. These are not YAML params.

Param (YAML)Sent to API asRequiredCode defaultNotes
namenameYes*Chat titleFull name. *Defaults to chat title if omitted. Can use contact_first_name + contact_last_name instead.
phoneNumberphoneNoFormatted phone, digits onlyMobile phone. Formatted channel phone (no dashes) used if omitted.
emailemailNoValid email address.
legacy_idlegacy_idNoExternal system ID.
is_orgis_orgNo01 to create an organization instead of a contact.
updateContactupdate_contactNoSet to 1 to update an existing contact. Identification requires id + at least one of each pair: phone/email, name/legacy_id.
ididNo**Required when updateContact is set. Plando contact ID to update.
approve_mailingapprove_mailingNo0 to opt the contact out of mailing.
tagstagsNoKeywords, comma-separated.
refer_emailrefer_emailNoComma-separated email(s) to notify with lead details. Set to 0 to suppress the notification email.
contact_first_namecontact[first_name]NoFirst name. Can be used instead of name.
contact_last_namecontact[last_name]NoLast name. Can be used instead of name.
contact_remarkcontact[remark]NoNote / remark.
contact_main_citycontact[main_city]NoCity.
contact_main_addresscontact[main_address]NoAddress.
contact_customer_cat_idcontact[customer_cat_id]NoCustomer category ID. 0 = potential customer. Get IDs from Plando item categories.
contact_customer_sales_person_idcontact[customer_sales_person_id]NoPlando system ID of the assigned sales person / team member.
contact_lead_status_cat_idcontact[lead_status_cat_id]NoNumeric ID of the lead process status (from Plando item categories).
contact_lead_origin_cat_idcontact[lead_origin_cat_id]NoNumeric ID of the lead origin source (from Plando item categories).
(any contact_*)contact[*]NoAny custom Plando contact field. E.g. contact_category_9: "123"contact[category_9]=123.
(any other param)same keyNoAny remaining params are passed as-is to the form body.

Result: { success: true, crmData: { id: contact_id } }. The new/updated contact's Plando ID is accessible as %chat:crmData.id%.

The op returns on_failure if the API responds with err !== "0" or does not return a contact_id.

Advanced — new lead with custom category fields

  plando_new_lead_with_fields:
type: func
func_type: crm
func_id: newOpportunity
params:
contact_first_name: "%state:node.ask_name.text%"
contact_lead_origin_cat_id: "724240"
contact_lead_status_cat_id: "323140"
contact_customer_sales_person_id: "4512"
tags: "whatsapp,bot"
on_complete: lead_created
on_failure: lead_failed

Advanced — update existing contact

  plando_update_contact:
type: func
func_type: crm
func_id: newOpportunity
params:
updateContact: 1
id: "%chat:crmData.contact_id%"
email: "%state:node.ask_email.text%"
name: "%chat:crmData.name%"
contact_lead_status_cat_id: "601305"
on_complete: contact_updated
on_failure: update_failed

openTicket / closeTicket

Pushes today's conversation transcript to Plando. Both openTicket and closeTicket use the same handler (POST /contacts/parse_whatsapp_session) and behave identically.

When it runs: Most commonly triggered automatically when an agent resolves a chat (if the integration is configured to do so). Can also be called manually from bot YAML to push a transcript mid-flow.

Basic

  plando_push_transcript:
type: func
func_type: crm
func_id: closeTicket
on_complete: done
on_failure: done
ParamRequiredNotes
emailNoOverride the agent email used as user_email. If omitted, uses the assigned agent's email, then falls back to crmConfig.defaultEmail.

What is sent:

FieldValue
user_emailResolved agent email (see above)
formal_whatsapp_url{customerId}.texterchat.com
phoneFormatted channel phone (digits only)
msgJSON array of today's messages — includes message (text), timestamp, from, to, and media (with 7-day shared download links for files)

Returns on_failure if: no email can be resolved, customerId is missing from config, or the API returns a non-200 result code.


Out of Adapter Scope

The following endpoints are not covered by the adapter. Use the request func instead.

Create activity record on a contact

Log an activity (e.g. "came from Meta ad", "sent template") on an existing Plando contact using a pre-configured record type.

  plando_log_activity:
type: func
func_type: system
func_id: request
params:
url: "https://plando.co.il/contacts/crm_form"
method: post
keepResponse: true
useProxy: true
headers:
Content-Type: "application/x-www-form-urlencoded; charset=utf-8"
data:
phone: "%chat:channelInfo.id%"
record[record_type_id]: YOUR_RECORD_TYPE_ID
access_key: "YOUR_ACCESS_KEY"
no_redirect: 1
on_complete: next_node
on_failure: fallback_node

Contact identification — provide at least one of: phone, contact_id, or email.

FieldRequiredNotes
phoneOne of the threeContact's phone number.
contact_idOne of the threePlando contact ID — available as %chat:crmData.contact_id% after getCustomerDetails.
emailOne of the threeContact's email address.
record[record_type_id]YesActivity/record type ID (number). Defined in Plando — get from the customer's Plando account.
access_keyYesAPI token (crmConfig.token).
no_redirectYesAlways 1.
record[description]NoFree-text description of the activity record.
record[actual_date]NoDate of the activity.
record[start_time]NoActivity start time. Format: "dd/mm/yyyy HH:MM".
record[end_time]NoActivity end time. Format: "dd/mm/yyyy HH:MM".
task_detailsNoFree text attached to the activity (custom per-record notes).
send_emailNoSet to 1 to send an email notification for this activity.
org_custom_value[field_name]NoPass a custom org field value. Replace field_name with the Plando field name.
record_idNoExisting Plando record ID. Only needed when updating or deleting a record (used with mark_to_delete).
mark_to_deleteNoSet to 1 to delete the record specified by record_id.

Response: On success (err: "0"), the API returns contact_id and record_id. Accessible via %state:node.plando_log_activity.*% when keepResponse: true.

Upload a file to a contact

Attach a file to a Plando contact after sharing it with shareFile.

  share_file:
type: func
func_type: system
func_id: shareFile
params:
file_node: upload_doc_user
on_complete: plando_upload_file

plando_upload_file:
type: func
func_type: system
func_id: request
params:
url: "https://plando.co.il/api/upload_contact_file"
method: post
keepResponse: true
json: true
useProxy: true
headers:
Content-Type: application/json
X-Access-Key: "YOUR_ACCESS_KEY"
data:
contact_id: "%chat:crmData.contact_id%"
title: "%state:node.upload_doc_user.text%"
url: "%state:node.share_file.link%"
on_complete: upload_done
on_failure: upload_failed
FieldNotes
contact_idContact's Plando ID — available as %chat:crmData.contact_id% after getCustomerDetails.
titleDocument title shown in Plando.
urlShared file URL from the shareFile node — use %state:node.<shareFile_node_name>.link%.
X-Access-KeyAPI token (crmConfig.token).
tip

shareFile generates a temporary download link valid for 7 days. Make sure plando_upload_file runs immediately after shareFile so Plando can fetch the file while the link is still active.


Plando Onboarding (for Texter Support)

Contact Plando support to obtain credentials.

Customer DB — crmConfig fields

FieldRequiredUse
tokenYesAPI access key (access_key). Provided by the customer from their Plando account.
chatYesPlando chat ID. Provided by the customer.
customerIdFor openTicket/closeTicketTexter tenant subdomain (e.g. mycompanymycompany.texterchat.com).
defaultEmailFor openTicket/closeTicket (recommended)Fallback agent email for transcript push.
attrFieldsRecommendedComma-separated list of contact attribute fields to fetch in getCustomerDetails. Agree with the customer which Plando category fields they use.
statusFieldNoContact field to expose as crmData.status in the Texter CRM panel.
idFieldNoContact field to expose as crmData.id in the Texter CRM panel.
pullContactByFieldNo{ "fieldName": "value" } — used when multiple contacts can share the same phone and you need to select by a specific field.
failOnMultipleContactsNoSet true to hard-fail on ambiguous phone matches.
closeTicketMaxMessagesCountNoMax messages in transcript. Default 30.