> For the complete documentation index, see [llms.txt](https://docs.graspil.com/en/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.graspil.com/en/connect-bot/api.md).

# Connecting a bot via API

> Graspil offers different ways to connect a bot to the system. Here we describe the connection method using the API.
>
> In the Dashboard, when connecting a bot, you can review all available connection options.

There are two methods of sending data to graspil via the API:

1. [Batch data sending](#paketnaya-otpravka-dannykh) — the preferred option
2. [Sending data at the moment it is received](#otpravka-dannykh-v-moment-polucheniya)

{% hint style="info" %}
In this article, "data" refers to a set of Update[^1] objects
{% endhint %}

In graspil, it's important to get the exact time your bot (code) received the Update[^1], down to the millisecond. That's why we recommend using the batch data sending method.

1. You can pass the exact time the data was received.
2. If you send data with a delay, for example once a minute, this will have a positive effect on the performance of all systems.

<details>

<summary>Why is the received date needed, and when do milliseconds matter</summary>

The received date of the Update[^1] object is needed simply because not all Update data types contain a date.

**Why milliseconds?**

They matter if you are also sending [outgoing traffi](#user-content-fn-2)[^2]c to graspil. It's important for the system to correctly sort the list of incoming and outgoing messages, and the only way to do this is by using the date.

Receiving and sending messages often happens within the same second, which is why we use milliseconds.

</details>

### Authorization

The Graspil API expects the API key to be included in all API requests, in a header that looks like this:

<table><thead><tr><th width="376">Name</th><th>Value</th></tr></thead><tbody><tr><td><code>Api-Key</code></td><td><code>meowmeowmeow</code></td></tr></tbody></table>

For more details on authorization and how to get an authorization key, see the [authorization section](/en/api/auth.md)

### Validating the Update structure

In both methods, the system expects to receive Updates[^1] that fully match the Telegram Bot API structure.

To speed things up, when the data is received the system only checks the basic parts of the data. A full check, including compliance with the Telegram Bot API structure, happens later. If errors occur, they will appear in the "[Bot errors](https://app.graspil.com/bot_errors)" section

{% hint style="info" %}
We recommend sending data exactly as you received it from Telegram. If you decide to collect the update yourself, make sure the data structure is 100% compliant with the Telegram Bot API, and also make sure you're sending all the necessary data to graspil, otherwise this may distort the reports.

Examples of the update structure are available in the documentation at <https://core.telegram.org/bots/webhooks#testing-your-bot-with-updates>
{% endhint %}

## Batch data sending

<mark style="color:green;">`POST`</mark> `https://api.graspil.com/v1/send-batch-update`

A method for sending [Update](https://core.telegram.org/bots/api#update) objects in batches. You can send up to 1k updates, each with its own received date. To send data, you need to submit an array of data.

**Headers**

<table><thead><tr><th width="376">Name</th><th>Value</th></tr></thead><tbody><tr><td>Content-Type</td><td><code>application/json</code></td></tr><tr><td>Api-Key</td><td><code>meowmeowmeow</code></td></tr></tbody></table>

**Body**

<table><thead><tr><th width="128">Parameter</th><th width="123">Type</th><th width="147">Required</th><th>Description</th></tr></thead><tbody><tr><td>date</td><td>RFC 3339 (<a href="https://en.wikipedia.org/wiki/ISO_8601">ISO 8601</a>)</td><td>No</td><td><p>The time the bot received this specific update. If not provided, the current time will be used.</p><p>The time format must include milliseconds and a time zone.<br>Example: <code>2024-08-03T20:00:00.123+02:00</code></p></td></tr><tr><td>update</td><td>An <a href="https://core.telegram.org/bots/api#update">Update</a> object</td><td>yes</td><td>A single <a href="https://core.telegram.org/bots/api#update">Update</a> object, the data you received from Telegram</td></tr></tbody></table>

{% hint style="danger" %}
The method accepts up to 1000 [Update](https://core.telegram.org/bots/api#update) objects per request
{% endhint %}

<details>

<summary>Example request body</summary>

{% code overflow="wrap" lineNumbers="true" %}

```json
[
    {
        "date": "2024-08-03T20:00:00.123+02:00", // date and time the data was received
        "update": {
            "message": {
                "chat": {
                    "id": 123,
                    "type": "private",
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "date": 1718691840,
                "from": {
                    "id": 123,
                    "is_bot": false,
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "text": "Hi, how are you?",
                "message_id": 1000
            },
            "update_id": 22111111
        }
    },
    {
        "update": {
            "message": {
                "chat": {
                    "id": 123,
                    "type": "private",
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "date": 1718691840,
                "from": {
                    "id": 123,
                    "is_bot": false,
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "text": "Hi, how are you?",
                "message_id": 1000
            },
            "update_id": 22111112
        }
    }
]
```

{% endcode %}

</details>

#### Code examples

<details>

<summary>Python</summary>

{% code overflow="wrap" lineNumbers="true" %}

```python
import requests
import json

url = "https://api.graspil.com/v1/send-batch-update"
api_key = "< API KEY >"

payload = json.dumps([
  {
    "date": "2024-08-03T20:00:00.123+02:00",
    "update": {
        "message": {
            "chat": {
                "id": 123,
                "type": "private",
                "username": "Graspil",
                "last_name": "Graspil",
                "first_name": "Bot"
            },
            "date": 1718691840,
            "from": {
                "id": 123,
                "is_bot": false,
                "username": "Graspil",
                "last_name": "Graspil",
                "first_name": "Bot"
            },
            "text": "Hi, how are you?",
            "message_id": 1000
        },
        "update_id": 22111112
    }
  }
])
headers = {
  'Content-Type': 'application/json',
  'Api-Key': api_key,
}

response = requests.request("POST", url, headers=headers, data=payload)

print(response.text)

```

{% endcode %}

</details>

<details>

<summary>JS</summary>

{% code overflow="wrap" lineNumbers="true" %}

```javascript
var request = require('request');
var api_key = '< API KEY >'
var options = {
  'method': 'POST',
  'url': 'https://api.graspil.com/v1/send-batch-update',
  'headers': {
    'Content-Type': 'application/json',
    'Api-Key': api_key,
  },
  body: JSON.stringify([
    {
      "date": "2024-08-03T20:00:00.123+02:00",
      "update": {
        "message": {
          "chat": {
            "id": 123,
            "type": "private",
            "username": "Graspil",
            "last_name": "Graspil",
            "first_name": "Bot"
          },
          "date": 1718691840,
          "from": {
            "id": 123,
            "is_bot": false,
            "username": "Graspil",
            "last_name": "Graspil",
            "first_name": "Bot"
          },
          "text": "Hi, how are you?",
          "message_id": 1000
        },
        "update_id": 22111111
      }
    }
  ])

};
request(options, function (error, response) {
  if (error) throw new Error(error);
  console.log(response.body);
});

```

{% endcode %}

</details>

<details>

<summary>PHP</summary>

{% code overflow="wrap" lineNumbers="true" %}

```php
$curl = curl_init();

curl_setopt_array($curl, [
  CURLOPT_URL => 'https://api.graspil.com/v1/send-batch-update',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS =>'[
    {
        "date": "2024-08-03T20:00:00.123+02:00",
        "update": {
            "message": {
                "chat": {
                    "id": 123,
                    "type": "private",
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "date": 1718691840,
                "from": {
                    "id": 123,
                    "is_bot": false,
                    "username": "Graspil",
                    "last_name": "Graspil",
                    "first_name": "Bot"
                },
                "text": "Hi, how are you?",
                "message_id": 1000
            },
            "update_id": 22111112
        }
    }
]',
  CURLOPT_HTTPHEADER => [
    'Content-Type: application/json',
    'Api-Key: ' . $api_key
  ],
]);

$response = curl_exec($curl);

curl_close($curl);
echo $response;
```

{% endcode %}

</details>

**Response**

{% tabs %}
{% tab title="200" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": true
}
```

{% endcode %}
{% endtab %}

{% tab title="400" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": false,
  "error_code": 400,
  "description": "Too many updates. Max 1000"
}
```

{% endcode %}
{% endtab %}

{% tab title="401" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": false,
  "error_code": 401,
  "description": "Unauthorized"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## Sending data at the moment it is received

<mark style="color:green;">`POST`</mark> `https://api.graspil.com/api/send-update`

The moment you receive data from the Telegram Bot API, you need to send that data to our platform. The data must be sent unchanged, matching the Telegram Bot API data structure.

{% hint style="warning" %}
For the system to work correctly, it's important to send data at the moment it is received. Alternatively, use the [send-batch-update](#send-batch-update) method, adding the received date, if you're sending the data later.
{% endhint %}

Data received from Telegram can have two different structures, depending on the update delivery method — **webhook** or **getUpdate**. This method supports both structures.

**Headers**

| Name         | Value              |
| ------------ | ------------------ |
| Content-Type | `application/json` |
| Api-Key      | `meowmeowmeow`     |

**Body**

<details>

<summary>Example request body (webhook bot type)</summary>

{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "update_id": 123,
  "message":{
    "date": 1691489960,
    "chat":{...}, // <----- shortened, contains the Chat object from the TG API
    "message_id": 123,
    "from":{...}, // <----- shortened, contains the User object from the TG API
    "text":"/start"
  }
}
```

{% endcode %}

</details>

<details>

<summary>Example request body (getUpdates bot type)</summary>

{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok":true,
  "result":[
    {
      "update_id": 123,
      "message":{...} // <- shortened, contains the Message object from the TG API
    },
    {
      "update_id": 124,
      "message":{...} // <- shortened, contains the Message object from the TG API
    }
  ]
}
```

{% endcode %}

</details>

#### Code examples

<details>

<summary>Python</summary>

{% code overflow="wrap" lineNumbers="true" %}

```python
import requests

url = "https://api.graspil.com/v1/send-update"
api_key = ""  # your API key
data = {}  # received data from telegram

headers = {
    "Api-Key": api_key,
    "Content-Type": "application/json"
}

response = requests.post(url, json=data, headers=headers)

# Response processing
print(response.text)
```

{% endcode %}

</details>

<details>

<summary>PHP</summary>

{% code overflow="wrap" lineNumbers="true" %}

```php
$url = "https://api.graspil.com/v1/send-update";
$api_key = ""; // your API key
//$data - received data from telegram for sending

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Api-Key: ' . $api_key,
    'Content-Type: application/json;'
)];
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);

$response = curl_exec($ch);
curl_close($ch);
```

{% endcode %}

</details>

**Response**

{% tabs %}
{% tab title="200" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": true
}
```

{% endcode %}
{% endtab %}

{% tab title="400" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": false,
  "error_code": 400,
  "description": "Wrong json"
}
```

{% endcode %}
{% endtab %}

{% tab title="401" %}
{% code overflow="wrap" lineNumbers="true" %}

```json
{
  "ok": false,
  "error_code": 401,
  "description": "Unauthorized"
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

## For developers

Develop an SDK in your programming language to connect to graspil. Publish this repository on GitHub and write to us at <mail@graspil.com>.

We'll add a link to your repository in the documentation, which will bring extra visitors to your page. We can also provide free access to the premium plan for several months and early access to the referral program.

[^1]: A standard [object](https://core.telegram.org/bots/api#update) with data from TG.

[^2]: Data that your bot sends to the user
