# Built-in variables

Some data reaches the code without any function calls — in ready-made JavaScript variables. The set depends on the block the code runs in.

## Contact data

In all blocks except the "Incoming webhook", the data of the contact the code runs for is available right away. In the "Incoming webhook" it appears once the code finds the contact with a [contact lookup function](https://support.watbot.org/api/javascript/contact).

| Variable | What it holds |
|---|---|
| `id` | The contact's ID on the platform |
| `bot_id` | The bot ID |
| `name` | The contact's full name |
| `first_name` | The first word of the name |
| `last_name` | The second word of the name |
| `phone` | Phone |
| `email` | Email |
| `address` | Address |
| `username` | The username in the messenger: `@flower_lover` in Telegram and MAX, `id123456` in VK |
| `telegram_id` | The person's ID in Telegram |
| `max_id` | The person's ID in MAX |
| `created_at` | When the contact appeared in the bot, in the form `2026-01-31 12:00:00` (UTC) |

The values are strings, including `id` and `bot_id`. In the "Incoming webhook", `id` and `bot_id` come as numbers, so bring them to one form before comparing: `Number(id) === 12345`.

If the contact lacks something — a phone, say — the variable does not exist at all, and referring to it stops the code with a `ReferenceError`. Check such variables with `typeof`:

```js
if (typeof phone !== 'undefined') {
    setContactVariable('courier_phone', phone);
} else {
    sendMessage('Please leave a phone number for the courier.');
}
```

In the "Incoming webhook", a few more variables appear after the contact is chosen — also only if the contact has a value:

| Variable | What it holds |
|---|---|
| `start_message` | The first message the contact sent to the bot |
| `amocrm_lead_id`, `amocrm_contact_id` | The deal and contact IDs in amoCRM |
| `bitrix_lead_id`, `bitrix_deal_id`, `bitrix_contact_id` | The lead, deal and contact IDs in Bitrix24 |

Contact variables and the bot's global variables do not come as ready-made variables — read them with the [`getContactVariable` and `getGlobalVariable`](10-variables.md) functions.

## Server response

In the code of the ["HTTP request"](https://support.watbot.org/chatbots/blocks/developer/http) block, the server response is in the `response` object:

| Field | What it holds |
|---|---|
| `response.status` | The response code, a number: `200`, `404` and so on |
| `response.body` | The response body as a string, as it arrived |
| `response.data` | The response body parsed as JSON. If the response is not JSON, this is an empty object `{}` |

The code starts only when the server has responded. If there is no response — the server did not respond within the time in the "Timeout" field or the connection could not be established — the block leaves through the "No response from server" output, and the code does not run. A response with an error code, such as `500`, is a normal response: the code runs, so check `response.status` yourself.

The code runs after the block's other settings: the variables from "Write json response to variables" have already been written by then.

```js
if (response.status !== 200) {
    sendMessage('The delivery service is unavailable right now, please try again later.');
    disableContinue();
} else if (response.data.slots && response.data.slots.length > 0) {
    setContactVariable('next_delivery', response.data.slots[0].time);
} else {
    sendMessage('There are no free delivery slots for today.');
}
```

## Incoming request

In the code of the ["Incoming webhook"](https://support.watbot.org/chatbots/blocks/developer/incoming-webhook) block, the incoming request is in the `request` object:

| Field | What it holds |
|---|---|
| `request.query` | Parameters from the query string. The values are strings |
| `request.headers` | Request headers. Names are in lower case: `request.headers['content-type']` |
| `request.body` | The request body as a string, as it arrived |
| `request.data` | All request parameters together: from the query string, the form and a JSON body. Numbers and booleans from JSON stay numbers and `true`/`false` |

If the request has no parameters, `request.query` is an empty object. Check nested fields before using them, so the code does not stop on `undefined`:

```js
var order = request.data.order;

if (order && order.contact_id && setContactById(order.contact_id)) {
    setContactVariable('order_number', String(order.id));
    sendMessage('Order No. ' + order.id + ' is packed and handed to the courier.');
}
```

If the sender signs its requests, you can check the signature with the [`hash_hmac`](30-crypto.md#hashhmac) function — using `request.body` and the signature header.

## Sheet rows

In the code of the ["Read rows from Google Sheets"](https://support.watbot.org/chatbots/blocks/lists/google-sheet-reader) block, the rows found are in `sheet.data` — an array of rows, where each row is an array of cells.

- `sheet.data` holds only the rows that passed the block's filters, and no more than set in "Number of records in a message".
- The cells are strings. The first cell of the array is column `A`.
- The block loads columns up to the rightmost one mentioned in its settings. For the code to get other columns too, call `setColumnRange("A:F")` with the range you need at the start of the code — the block reads this call before querying the sheet. Google does not send empty cells at the end of a row, so rows may differ in length.
- If no rows are found, the code does not run: the block leaves through the "No records found" output.

```js
setColumnRange("A:C");

var rows = sheet.data;
var total = 0;

for (var i = 0; i < rows.length; i++) {
    total += Number(rows[i][2] || 0);
}

setContactVariable('order_total', total);
```

Here column `C` holds the bouquet price, and the code adds up the prices of all rows found.
