How to Test Your Handler for Processing Bitrix24 Events
If you are developing integrations for Bitrix24 using AI tools (Codex, Claude Code, Cursor), connect to the MCP server so that the assistant can utilize the official REST documentation.
A test handler helps verify that Bitrix24 can send an event to your server and that the server receives and retains the event data. To test, register a ONAPPTEST event handler using the event.bind method, then call the event.test method.
The scenario consists of four steps:
- Create a
handler.phpfile that saves the inbound request to a file - Register a
ONAPPTESTevent handler using the event.bind method - Call a test event using the
event.testmethod - Verify that a file containing the event data appears in the
logfolder
Prepare the Handler
To execute the scenario, you need:
- An application with OAuth authorization
- A public URL for the handler, accessible from an external network for GET and POST requests
- A
handler.phpfile on your server - A writable
logfolder located next to thehandler.phpfile - An OAuth access token to call the
event.bindandevent.testmethods
Create a handler.php file on your server. Ensure the file is accessible from the internet. Create a log folder next to the file.
The code in the handler.php file saves the inbound request to a separate file:
How to Use Examples in Documentation
<?
file_put_contents(
__DIR__ . '/log/' . time() . '.txt',
var_export($_REQUEST, true)
);
Register a Test Event
Register the ONAPPTEST event using the event.bind method. Pass the public URL of the handler.php file in the handler parameter.
Replace the values in the examples:
https://example.com/handler.phpwith your handler URL**put_access_token_here**with your OAuth access token**put_your_bitrix24_address**with your Bitrix24 address
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"event":"ONAPPTEST","handler":"https://example.com/handler.php","auth":"**put_access_token_here**"}' \
https://**put_your_bitrix24_address**/rest/event.bind
// This snippet is an ES module: top-level await requires type="module" or a bundler.
// $b24 is an already-initialized SDK instance (see the SDK "Get started" guide).
import { Text } from '@bitrix24/b24jssdk'
import type { B24Frame } from '@bitrix24/b24jssdk'
declare const $b24: B24Frame
try {
const response = await $b24.actions.v2.call.make<boolean>({
method: 'event.bind',
params: {
event: 'ONAPPTEST',
handler: 'https://example.com/handler.php',
},
requestId: Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
} else {
const result = response.getData()!.result
console.info('event.bind result:', result)
}
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
<!-- Load the SDK (UMD build); it is exposed as the global B24Js -->
<script src="https://unpkg.com/@bitrix24/b24jssdk@1/dist/umd/index.min.js"></script>
<script>
async function bindEvent() {
try {
// Initialize the SDK inside a Bitrix24 frame
const $b24 = await B24Js.initializeB24Frame()
const response = await $b24.actions.v2.call.make({
method: 'event.bind',
params: {
event: 'ONAPPTEST',
handler: 'https://example.com/handler.php',
},
requestId: B24Js.Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
return
}
const result = response.getData().result
console.info('event.bind result:', result)
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
}
document.addEventListener('DOMContentLoaded', bindEvent)
</script>
<?
$eventBind = CRest::call(
'event.bind',
[
'event' => 'ONAPPTEST',
'handler' => 'https://example.com/handler.php'
]
);
if($eventBind['result'])
{
echo 'event bind successful';
}
?>
// client and ctx are already created — see the Go SDK section
res, err := client.Core().Call(ctx, "event.bind", b24.Params{
"event": "ONAPPTEST",
"handler": "https://example.com/handler.php",
})
if err != nil {
return fmt.Errorf("event.bind: %w", err)
}
var ok bool
if err := json.Unmarshal(res.Result, &ok); err != nil {
return fmt.Errorf("parse response: %w", err)
}
fmt.Println("done:", ok)
A successful registration returns true.
{
"result": true
}
Call the Test Event
Call the event.test method with arbitrary data. Bitrix24 will send the ONAPPTEST event to the URL you specified when registering the handler.
The event.test method works only with application OAuth authorization. It is not suitable for incoming webhooks: with a different authorization type, the method returns an authorization type error.
In the example, the any parameter is used as a test value. After the call, it should appear in the saved request within the data.QUERY block.
curl -X POST \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"any":"data","auth":"**put_access_token_here**"}' \
https://**put_your_bitrix24_address**/rest/event.test
// This snippet is an ES module: top-level await requires type="module" or a bundler.
// $b24 is an already-initialized SDK instance (see the SDK "Get started" guide).
import { Text } from '@bitrix24/b24jssdk'
import type { B24Frame } from '@bitrix24/b24jssdk'
declare const $b24: B24Frame
try {
const response = await $b24.actions.v2.call.make<number>({
method: 'event.test',
params: {
any: 'data',
},
requestId: Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
} else {
const result = response.getData()!.result
console.info('event.test result:', result)
}
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
<!-- Load the SDK (UMD build); it is exposed as the global B24Js -->
<script src="https://unpkg.com/@bitrix24/b24jssdk@1/dist/umd/index.min.js"></script>
<script>
async function testEvent() {
try {
// Initialize the SDK inside a Bitrix24 frame
const $b24 = await B24Js.initializeB24Frame()
const response = await $b24.actions.v2.call.make({
method: 'event.test',
params: {
any: 'data',
},
requestId: B24Js.Text.getUuidRfc4122()
})
// The payload is available only on a successful response
if (!response.isSuccess) {
console.error(response.getErrorMessages().join('; '))
return
}
const result = response.getData().result
console.info('event.test result:', result)
} catch (error) {
// Thrown on transport or SDK failures (AjaxError, SdkError, etc.)
console.error(error)
}
}
document.addEventListener('DOMContentLoaded', testEvent)
</script>
<?
$result = CRest::call(
'event.test',
[
'any' => 'data'
]
);
if($result['result'])
{
echo 'successful';
}
?>
// client and ctx are already created — see the Go SDK section
res, err := client.Core().Call(ctx, "event.test", b24.Params{
"any": "data",
})
if err != nil {
return fmt.Errorf("event.test: %w", err)
}
var value b24.ID
if err := json.Unmarshal(res.Result, &value); err != nil {
return fmt.Errorf("parse response: %w", err)
}
fmt.Println("result:", value)
A successful call to the event.test method returns 1.
{
"result": 1
}
Verify the Result
Open the log folder located next to the handler.php file. If the scenario is executed successfully, a file containing the event data will appear in it.
The file should contain:
eventwith the valueONAPPTESTevent_handler_idwith the identifier of the registered handlerdata.QUERY.anywith the valuedataauthwith the event authorization data
array (
'event' => 'ONAPPTEST',
'event_handler_id' => 1,
'data' =>
array (
'QUERY' =>
array (
'any' => 'data',
),
'LANGUAGE_ID' => 'en',
),
'ts' => '1573120286',
'auth' => array (...)
)
If the file is created and contains data.QUERY.any, the handler is accessible from Bitrix24 and accepts event data.
Errors and Diagnostics
If the event.bind method returns an error, check the registration parameters:
ERROR_EVENT_NOT_FOUND— an incorrect event is specified in theeventparameter. To test the handler, useONAPPTESTHANDLERwas not passed — specify a public URL for thehandler.phpfileUnable to set event handler— check if a handler with the same URL is already registered- Access error — check the OAuth token and the application context
If the event.bind method returns false or the event.test method returns a successful response, but the file does not appear in the log folder, check the handler:
- The
handlerURL is accessible from the internet and does not point tolocalhost - The server accepts POST requests to the
handler.phpfile - The
logfolder exists alongside thehandler.phpfile - The web server has write permissions for the
logfolder - There are no PHP errors in the handler code
Key Considerations
The event.test method only verifies the delivery of a test event ONAPPTEST. For production events, use the event codes from the list returned by the events method and register them using the event.bind method.
Do not save authorization tokens from the auth block into public logs. In the example, the handler records the entire request only for quick verification of event reception.
After verification, delete the files from the log folder or close external access to it. If the test handler is no longer needed, remove the subscription using the event.unbind method.