Most leave processes break in the same place. The manager approves the request, the decision lands in a chat notification, and then somebody has to remember to open the spreadsheet and change a cell. When they forget, or type the wrong thing, the database and reality quietly drift apart.
This guide closes that loop. Lark Base holds the data, Lark Approval makes the decision, and AnyCross wires them together so the record updates itself the moment a manager taps Approve or Reject. Nobody touches the database by hand.
It is a long build, but every piece is configuration rather than code. Set aside an afternoon.
What You Are Building
Two AnyCross workflows do the work.
Workflow 1 fires when someone submits the leave form. It logs the request in Lark Base as Pending, notifies the manager, formats the data, creates a formal approval instance, then writes the approval’s unique ID back onto the Base record so the two systems are linked.
Workflow 2 fires when the approval status changes. It uses that stored Approval ID to find the right record, then branches on the decision and writes Approve or Reject into the Status column.
Important: Use an administrator account throughout. Standard accounts hit permission walls at the Developer Console and Admin Console steps, and you will not be able to finish.
Part 1: Build the Lark Base
Create the table
Create a base and set up a table with these fields.
- No: Serial number for indexing.
- Name: The employee requesting leave.
- Leave start date and Leave end date: The leave period.
- Reason: Why the leave is being taken.
- Status: A single option field holding Pending, Approve or Reject.
- Respondents: The applicant’s user profile, captured for identity verification.
- Submitted on: Timestamp of the submission.
- Approval ID: The code that links this record to its approval instance.
The Status options matter more than they look. Whatever you type here has to be matched character for character later in AnyCross.
Create the form
Add a form view collecting Name, Leave start date, Leave end date and Reason. This is what employees actually see.
Add the Base workflow
The base needs to tell AnyCross when a request arrives. Create a workflow with two nodes.
For the trigger, choose When a new record is added, select your table, and pick the Reason field. Then set two conditions: Reason is not empty, and Status is Pending.
For the second node, choose HTTP request:
- Method: POST.
- URL: your AnyCross webhook callback URL. You do not have this yet, so leave it blank and come back after Part 4.
- Headers: Content-type set to application/json.
- Request body: JSON format, mapping Name, start_date, end_date, Reason and Status to the record’s fields.
- Response body: None.
Note: The field names you use in the request body become the variable names in AnyCross. Keep them exactly as shown and the rest of the guide will line up.
Part 2: Create the Custom App
AnyCross needs an app identity to act on your behalf. Skip this part if you already have a suitable custom app.
Go to the Lark Developer platform, open the Developer Console, and click Create Custom App.
Give it a name and description, pick an icon, then click Create.
On the app dashboard, click Create Version in the banner at the top.
Enter a version number such as 1.0.0, add update notes, and click Save.
Submit the release request. Depending on your organisation’s policy this either goes to an administrator for review or clears immediately, after which you click Publish.
Part 3: Create the Approval Form
In the Lark Admin Console, create a new approval.
Set the name to Leave Request and make it visible to everyone under Basic Info.
Under Form Design, drag in widgets for Name, Start Date, End Date and Reason. You can add more, but every widget you add here must have a matching field in your Lark Base.
Under Process Design, select the approval node and set the approver. For a live deployment choose Manager. For testing on your own account, choose Requester so the request comes back to you.
Find your approval definition code
You will need this shortly. Open the approval in the Admin Console and look at the browser address bar. The definitionCode parameter at the end of the URL is the value to copy.
Part 4: AnyCross Workflow 1, the Approval Request
Node 1: Webhook trigger
Go to Integration, create a workflow called Approval Request, and select Webhook Trigger.
On the Trigger tab, choose Asynchronous URL trigger.
Switch to Settings, copy the Callback URL, and set the request body type to JSON. Paste that URL into the HTTP request node you left blank in Part 1.
Important: Note the Authentication method and IP allowlist fields on this screen. By default the endpoint is unauthenticated, which means anyone holding the URL can post data into your base. Treat the callback URL as a secret, and consider adding an IP allowlist before you go live.
Node 2: Lark Base, search records
Add a Lark Base node and choose Search records.
On the Auth tab, click + Create authentication.
Name the connection, choose the Enhanced authentication version, set the type to Lark Tenant Authorization, pick the custom app you published in Part 2, then click Create and Connect.
On the Input tab, configure:
- Base and Table id: your leave request base and table.
- User ID categories: open_id.
- Page size: 1.
- Sorting conditions: field name No, descending order true. This grabs the newest record.
- Filter: Status is Pending.
Tip: The filter value has to match your Base field option exactly. “Pending” and “pending” are different strings as far as this node is concerned.
Node 3: Lark Message, notify the manager (optional)
This node is not required for the loop to work, but it is what makes the system usable day to day.
Add a Lark Message node and choose Send common message.
On the Auth tab, select the authentication you just created.
In the Input configuration, write your message content and set the Receiver ID to the manager. Include a record link built from the record_id variable so the manager can jump straight to the entry.
The record_id variable comes from the search records node’s output.
Node 4: JSON Helper
The approval connector expects the form data in a specific shape. Add a JSON Helper node and choose JSON Parse.
Paste your payload into the JSON String field.
[
{
"id": "widget17688764968610001",
"type": "input",
"value": "{{webhook-trigger-1.body.Name}}"
},
{
"id": "widget17688921455010001",
"type": "date",
"value": "{{webhook-trigger-1.body.start_date}}T00:00:00+08:00"
},
{
"id": "widget17688921469730001",
"type": "date",
"value": "{{webhook-trigger-1.body.end_date}}T00:00:00+08:00"
},
{
"id": "widget17688765169960001",
"type": "input",
"value": "{{webhook-trigger-1.body.Reason}}"
}
]
Each object maps one approval form widget to one value from the webhook. Replace the widget IDs with your own, and note the timezone suffix on the date fields. Without T00:00:00+08:00 the approval system will reject the date.
Node 5: Lark Approval, create instance
Add a Lark Approval node and choose Create approval instance.
On the Input tab, paste your Approval definition code from Part 3 and set the Unique open ID of user to the applicant.
Then fill the JSON array, control value field. This is the same payload as the JSON Helper step, but written as a concatenated expression rather than plain JSON.
"[{\"id\":\"widget17688764968610001\",\"type\":\"input\",\"value\":\""+_("$.webhook-trigger-1.body.Name")+"\"},{\"id\":\"widget17688921455010001\",\"type\":\"date\",\"value\":\""+_("$.webhook-trigger-1.body.start_date")+"T00:00:00+08:00"+"\"},{\"id\":\"widget17688921469730001\",\"type\":\"date\",\"value\":\""+_("$.webhook-trigger-1.body.end_date")+"T00:00:00+08:00"+"\"},{\"id\":\"widget17688765169960001\",\"type\":\"input\",\"value\":\""+_("$.webhook-trigger-1.body.Reason")+"\"}]"
Node 6: Lark Base, update record
The final node closes the link between the two systems. Add a Lark Base node and choose Update a record.
Select your Base and Table, then map Record ID to the record_id variable from the search step.
Under Fields, map the Approval ID column to the instance_code variable produced by the approval node.
Important: This step is what makes Workflow 2 possible. Without the instance code stored on the record, the second workflow has no way to find which row a decision belongs to.
Click Done, then Publish.
Finding Widget IDs and open_id
Two values in Part 4 come from outside the AnyCross interface.
Widget IDs
Every field on a Lark approval form has an internal widget ID, in the format widget followed by a long number. These are specific to your form, so the IDs in the sample payload above will not work in your build.
The reliable way to retrieve them is the approval definition API. Call Get approval definition with your approval definition code, and the response returns the form structure with each widget’s ID and type. You can run this from the API Explorer in the Developer Console without writing any code, using the custom app you published in Part 2.
Note: Map every widget in the order the fields appear on your approval form, and match the type value to the widget type. An input widget declared as a date, or the reverse, will fail silently.
The user’s open_id
An open_id looks like ou_ followed by a long hexadecimal string, and identifies one user within one organisation.
The easiest route is inside AnyCross itself. In the Lark Message node you configured in Node 3, the Receiver ID field lets you pick a person by name and resolves them to their open_id automatically, with Receiver ID type showing open_id underneath. Selecting a person there and reading back the resolved value avoids looking it up manually.
If you need it outside that context, the Developer Console’s API Explorer can return a user’s open_id from their email address or phone number.
Part 5: AnyCross Workflow 2, the Approval Status
Node 1: Lark Approval trigger
Create a second workflow called Approval Status and select Lark Approval as the trigger application.
Choose the Approval instance status changed event.
On the Settings tab, paste your approval definition code and set Accept Instance Status to PENDING, APPROVED and REJECTED so the workflow catches every stage.
Node 2: Lark Base, search records
Add a Lark Base node with the Search records action. Select your Base and Table, then set the filter so Approval ID equals the instance_code variable from the trigger.
This is the reverse of what Workflow 1 did. Workflow 1 wrote the instance code onto the record; Workflow 2 uses it to find the record again.
Node 3: Branch
Add a Branch node. Branches are mutually exclusive and evaluated left to right.
Create two conditions: one named If Approve where the value equals APPROVED, and one named If Reject where it equals REJECTED.
For each condition, set the left value to the status variable from the approval trigger and the right value to the literal text.
The status variable sits under the event message body in the trigger’s output.
Important: APPROVED and REJECTED must be in capitals. Lark sends the status in upper case, and a lower-case comparison will never match, so the workflow silently does nothing.
Node 4: Update the record on each branch
On the If Approve branch, add a Lark Base Update a record node. Map Record ID to the record_id variable and set the Status field to Approve.
Repeat on the If Reject branch, setting Status to Reject.
Tip: Notice the asymmetry. The branch compares against APPROVED in capitals, because that is what Lark Approval sends. The value written into Base is Approve, because that is what your Status field option says. Getting these the wrong way round is the single most common reason this build fails.
Click Done, then Publish.
How It Works End to End
An employee fills in the form and submits.
Within seconds the record appears in Lark Base with a Pending status and an Approval ID already populated, confirming the approval instance was created and linked.
The bot notifies the approver with a link straight to the record.
The approver receives a card carrying the request details and Approve and Reject buttons.
Once they decide, the card updates and the requester gets a confirmation message.
And the Base record updates itself. No admin, no retyping, no drift.
Common Reasons It Does Not Work
- Nothing reaches AnyCross. Check the callback URL is pasted into the Base HTTP node, the method is POST, and the header is application/json.
- The approval instance is not created. Widget IDs are wrong, or a date value is missing the T00:00:00+08:00 suffix.
- The branch never fires. APPROVED or REJECTED is not in capitals.
- The status does not update. The text written to Base does not exactly match a Status field option.
- Search records returns nothing. The filter value does not match, or the record is not actually Pending.
- Permission errors throughout. You are not on an administrator account, or the custom app was never published.
Practical Use Cases for SMEs and Startups
- Leave and time off: The build above, with a balance field deducted on approval.
- Purchase requisitions: Requests logged to Base, routed by amount, with the approved value written back for budget reporting.
- Expense claims: Receipts attached at submission, status synced so finance sees only approved claims.
- Client onboarding sign-off: Each stage approved by a different role, with the CRM record advancing automatically.
- Asset requests: Equipment bookings approved by a manager and reflected instantly in an asset register.
Frequently Asked Questions (FAQ)
What is Lark AnyCross used for?
AnyCross is Lark’s integration platform. It connects Lark products and third-party services into automated workflows, so an event in one system can trigger actions in another without any code.
Why do I need two workflows instead of one?
They respond to different events. The first reacts to a form submission and creates the approval; the second reacts to the manager’s decision and updates the record. A single workflow cannot wait indefinitely for a human to make up their mind.
What is the Approval ID for?
It is the link between the two systems. Workflow 1 writes the approval instance code onto the Base record, and Workflow 2 searches on that code to find the right row when a decision arrives.
Do I need a custom app to use AnyCross with Lark Base?
Yes. The Lark connectors authenticate through a custom app using Lark Tenant Authorization, so you need one published in the Developer Console before the nodes can connect.
Where do I find the approval definition code?
Open the approval in the Lark Admin Console and read the definitionCode parameter from the end of the browser URL.
Why is my branch not matching the approval status?
Almost always capitalisation. Lark Approval sends APPROVED and REJECTED in upper case, so the branch condition has to use upper case too. Separately, the value you write into Base must match your Status field option exactly, which is usually not upper case.
Can I use a manager as the approver instead of the requester?
Yes, and you should in production. Set the approver to Manager in Process Design. Requester is only useful for testing the loop on a single account.
Closing the Loop
The value here is not any one node. It is that the decision and the record can no longer disagree, because no human sits between them. Build it once for leave, and the same pattern, form to Base to approval and back again, covers purchase requests, expense claims and every other approval your team runs on memory and goodwill.
Ready to Power Your Business with Lark?
Lark Base is just one part of an all-in-one platform that brings messaging, meetings, documents, approvals, and automations together for your entire team.
As the Platinum Partner for Lark in Malaysia, Exabytes offers tailored Lark plans, hands-on onboarding, and dedicated local support to help your team build automations like this one properly the first time.







































































