Submit a URL through the API
Use POST /api/update to queue a public page for indexing or re-indexing in your Dzen Chat project. The examples below use the hosted service at https://chat.dzen.dev. For a local installation, change api_url or $apiUrl to https://local.dzenchat.com/api/update and configure trust for its TLS certificate.
Create an API client
- Open your project in Dzen Chat and choose Settings → API clients.
- Choose Add, enter a name, and select the website sources this client may update.
- Copy
CHAT_CLIENT_IDandCHAT_CLIENT_SECRET. The secret is displayed only once; store it in your server's secret manager or environment. - Set those environment variables in the process that runs your integration. Replace
https://example.com/docs/pagein the example with a public URL belonging to an assigned source.
Keep the secret on your server. Browser JavaScript must never contain it. For a manually created client, New secret invalidates the old secret immediately; update the calling application's environment before its next request. Integration-managed clients are changed through the integration's reconnection flow.
Sign the request
Send an application/x-www-form-urlencoded POST with these fields:
| Field | Value |
|---|---|
client_id |
Your API client ID. |
url |
The full public page URL to process. |
timestamp |
Current Unix time in seconds. The default allowed clock difference is 60 seconds. |
nonce |
A fresh random value for each request. Reused nonces are rejected. |
signature |
Lowercase hexadecimal HMAC-SHA256 calculated with the client secret. |
To calculate the signature, sort the four fields excluding signature by key and join the raw key=value strings with a newline, with no final newline:
client_id=...
nonce=...
timestamp=...
url=...
Sign the UTF-8 bytes before form encoding. Add the signature to the form and then encode the body. The examples generate the timestamp, nonce and signature for every call.
Python
Install requests in your application's virtual environment:
venv/bin/python -m pip install requests
Save the following as submit_url.py and run it with venv/bin/python submit_url.py after setting the two environment variables.
import hashlib
import hmac
import os
import secrets
import time
import requests
api_url = "https://chat.dzen.dev/api/update"
client_id = os.environ["CHAT_CLIENT_ID"]
client_secret = os.environ["CHAT_CLIENT_SECRET"]
url = "https://example.com/docs/page"
timestamp = str(int(time.time()))
nonce = secrets.token_hex(16)
form = {
"url": url,
"client_id": client_id,
"timestamp": timestamp,
"nonce": nonce,
}
payload = "\n".join(f"{key}={value}" for key, value in sorted(form.items()))
signature = hmac.new(
client_secret.encode("utf-8"),
payload.encode("utf-8"),
hashlib.sha256,
).hexdigest()
form["signature"] = signature
response = requests.post(
api_url,
data=form,
timeout=30,
)
response.raise_for_status()
print(response.json())
PHP
Use PHP with the cURL extension. Save this example as submit_url.php and run php submit_url.php with the same environment variables.
<?php
$apiUrl = 'https://chat.dzen.dev/api/update';
$clientId = getenv('CHAT_CLIENT_ID');
$clientSecret = getenv('CHAT_CLIENT_SECRET');
$url = 'https://example.com/docs/page';
if (!$clientId || !$clientSecret) {
throw new RuntimeException('Set CHAT_CLIENT_ID and CHAT_CLIENT_SECRET');
}
$timestamp = (string) time();
$nonce = bin2hex(random_bytes(16));
$form = [
'url' => $url,
'client_id' => $clientId,
'timestamp' => $timestamp,
'nonce' => $nonce,
];
ksort($form);
$payload = implode("\n", array_map(
static fn ($key, $value) => "{$key}={$value}",
array_keys($form),
$form
));
$signature = hash_hmac('sha256', $payload, $clientSecret);
$form['signature'] = $signature;
$body = http_build_query($form, '', '&');
$ch = curl_init($apiUrl);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $body,
CURLOPT_HTTPHEADER => ['Content-Type: application/x-www-form-urlencoded'],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 30,
]);
$response = curl_exec($ch);
if ($response === false) {
throw new RuntimeException(curl_error($ch));
}
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status < 200 || $status >= 300) {
throw new RuntimeException($response);
}
echo $response;
Response and troubleshooting
A successful request returns HTTP 202:
{
"status": "ok",
"action": "queued",
"url": "https://example.com/docs/page",
"final_url": null,
"message": "Document update queued"
}
This confirms that processing was queued. Check the page's status in Dzen Chat to confirm indexing completed.
| Status | What to check |
|---|---|
400 |
Required fields, URL syntax, and timestamp freshness. |
401 |
Active client, secret, exact signature payload, and a fresh nonce. |
403 |
Source assignment and allowed URL. Integration clients are restricted to their site's origin and path prefix. |
415 |
Send a form body, not JSON. |
429 |
Reduce request frequency; any later attempt needs a fresh timestamp, nonce and signature. |
Manual clients can submit URLs on assigned source domains and their subdomains. Integration clients additionally enforce the authorized site's scheme, host, port and path prefix, and cannot modify a page belonging to another source.
For a local TLS certificate, provide its issuing CA through REQUESTS_CA_BUNDLE for Python or configure PHP/cURL's CA trust. Keep certificate verification enabled.
The instance's OpenAPI reference describes the request schema. This form-based endpoint is separate from the Integration API required by the WordPress plugin.