Skip to main content

Webhooks

Webhooks allow you to receive real-time notifications when specific events occur in omik_polititablet. This feature was introduced in version 2.7.6 and provides a flexible way to integrate with external services like Discord, logging systems, or custom applications.

Overview

The webhook system supports subscribing to multiple events with a single webhook endpoint. Each webhook can be configured to listen to specific events, and when those events occur, the system will send an HTTP POST request to your configured URL with the event data.

Getting Started

Prerequisites

  • omik_polititablet version 2.7.6 or higher
  • A webhook endpoint URL (e.g., Discord webhook, custom server endpoint)

Setting Up Webhooks

  1. Navigate to admin settings in the UI
  2. Click "Add new webhook endpoint" to create a new webhook endpoint
  3. Configure your webhook:
    • Name: A descriptive name for your webhook
    • URL: The endpoint URL where webhook payloads will be sent
    • Events: Select one or more events you want to subscribe to

Configuring Webhook Handlers

Webhook handlers are configured in fivem/server/webhooks.lua. Each handler receives the webhook URL and payload data, allowing you to customize how the data is formatted and sent to your endpoint.

The default handlers are configured for Discord webhooks, but you can modify them to work with any service that accepts HTTP POST requests.

Available Events

post.created

Triggered when a new post is created in the system.

Payload Structure:

{
officer: { // Officer who created the post
name: string;
badge_number: string;
// ... other officer properties
};
title: string; // Post title
content: string; // Post content
};

Example Discord Embed:

{
title = "New Post",
color = 13311,
fields = {
{
name = "Title",
value = payload.title,
},
{
name = "Content",
value = payload.content,
},
{
name = "Author",
value = payload.officer.name .. " [" .. payload.officer.badge_number .. "]",
},
},
author = {
name = "omik_polititablet V2",
},
}

offense.created

Triggered when a new offense report is created.

Payload Structure:

{
person: string; // Name of the person being cited/arrested
officer: { // Primary officer
name: string;
badge_number: string;
// ... other officer properties
};
officers: Record<number, { // All involved officers
badge_number: string
name: string
rank: string
}>;
offenses: Record<string, {
ticket: {
id: number | string,
type: string,
law: string,
paragraph: string,
title: string,
cols: string
};
amount: number;
}>;
confiscated: any[]; // Items confiscated
lawyer: {
used: boolean; // Whether a lawyer was present
name: string; // Lawyer's name
};
weapons: any[]; // Means of power used
total_offense_amount: {
price: number; // Total fine amount
jail: number; // Total jail time
revocation: boolean; // License revocation
points: number; // License points
};
report: string; // Offense description/report
};

Example Discord Embed:

{
title = "New Offense",
color = 13311,
fields = {
{
name = "Citizen",
value = payload.person,
inline = true,
},
{
name = "Officer",
value = payload.officer.name .. " [" .. payload.officer.badge_number .. "]",
inline = true,
},
{
name = "Involved Officers",
value = "John Doe [101]\nJane Smith [102]",
inline = true,
},
{
name = "Lawyer",
value = payload.lawyer.used and payload.lawyer.name or "No lawyer",
inline = true,
},
{
name = "Charges",
value = "Multiple charges listed...",
},
{
name = "Description",
value = payload.report,
},
},
}

offense.deleted

Triggered when an offense report is deleted from the system.

Payload Structure:

{
name: string; // Name of the person whose offense was deleted
officer: { // Officer who deleted the offense
name: string;
badge_number: string;
// ... other officer properties
};
};

Example Discord Embed:

{
title = "Deleted Offense",
color = 13311,
fields = {
{
name = "Citizen",
value = payload.name,
inline = true,
},
{
name = "Officer",
value = payload.officer.name .. " [" .. payload.officer.badge_number .. "]",
inline = true,
},
},
}

employee.created

Triggered when a new employee is added to the system.

Payload Structure:

{
name: string; // Employee name
badge: string; // Badge number
rank: string; // Rank/position
responsibleArea: string; // Area of responsibility
profileLogo: string; // Profile logo URL
certificates: string[]; // List of certificates
educations: string[]; // List of educations/training
};

Example Discord Embed:

{
title = "New Employee",
color = 13311,
fields = {
{
name = "Name",
value = payload.name,
inline = true,
},
{
name = "Rank",
value = payload.rank,
inline = true,
},
{
name = "Badge Number",
value = payload.badge,
inline = true,
},
{
name = "Responsibility",
value = payload.responsibleArea,
inline = true,
},
{
name = "Certifications",
value = table.concat(payload.certifications, "\n") or "None",
inline = true,
},
{
name = "Educations",
value = table.concat(payload.educations, "\n") or "None",
inline = true,
},
},
}

warrant.created

Triggered when a new warrant is created.

Payload Structure:

{
type: "person" | "vehicle"; // Type of warrant
plate: string; // Vehicle plate (if type is "vehicle")
name: string; // Person name (if type is "person")
description: string; // Warrant description
offenses: Record<string, {
ticket: {
id: number | string,
type: string,
law: string,
paragraph: string,
title: string,
cols: string
};
amount: number;
}>;
officer: { // Officer who created the warrant
name: string;
badge_number: string;
// ... other officer properties
};
}

Example Discord Embed:

{
title = "New Warrant",
color = 13311,
fields = {
{
name = "Type",
value = payload.type,
inline = true,
},
{
name = payload.type == "person" and "Name" or "License Plate",
value = payload.type == "person" and payload.name or payload.plate,
inline = true,
},
{
name = "Officer",
value = payload.officer.name .. " [" .. payload.officer.badge_number .. "]",
inline = true,
},
{
name = "Charges",
value = "Multiple charges listed...",
},
{
name = "Description",
value = payload.description,
},
},
}

warrant.deleted

Triggered when a warrant is deleted.

Payload Structure:

{
type: "person" | "vehicle";
plate: string;
name: string;
description: string;
offenses: Record<string, {
ticket: {
id: number | string,
type: string,
law: string,
paragraph: string,
title: string,
cols: string
};
amount: number;
}>;
officer: {
name: string;
badge_number: string;
// ... other officer properties
};
}

Example Discord Embed:

{
title = "Warrant Deleted",
color = 13311,
fields = {
{
name = "Type",
value = payload.type,
inline = true,
},
{
name = payload.type == "person" and "Name" or "License Plate",
value = payload.type == "person" and payload.name or payload.plate,
inline = true,
},
{
name = "Officer",
value = payload.officer.name .. " [" .. payload.officer.badge_number .. "]",
inline = true,
},
{
name = "Charges",
value = "Multiple charges listed...",
},
{
name = "Description",
value = payload.description,
},
},
}

Customizing Webhook Handlers

You can customize how webhooks are sent by modifying the handlers in fivem/server/webhooks.lua. Each handler follows this pattern:

RegisterWebhookHandler("event.name", function(url, payload)
-- Your custom logic here

-- Example: Send to Discord
local embeds = {
{
title = "Event Title",
color = 13311,
fields = {
-- Your fields here
},
}
}

PerformHttpRequest(url, function(err, text, headers)
if err ~= 200 then
Log.warn("Failed to send webhook to " .. url .. ". Error: " .. tostring(err))
end
end, "POST", json.encode({ embeds = embeds }), { ["Content-Type"] = "application/json" })
end)

Non-Discord Webhooks

If you're not using Discord, you can modify the handlers to send data in any format:

RegisterWebhookHandler("event.name", function(url, payload)
-- Send raw JSON payload
local data = {
event = "event.name",
data = payload,
timestamp = os.time()
}

PerformHttpRequest(url, function(err, text, headers)
if err ~= 200 then
Log.warn("Failed to send webhook. Error: " .. tostring(err))
end
end, "POST", json.encode(data), { ["Content-Type"] = "application/json" })
end)

Troubleshooting

Webhooks Not Being Sent

  1. Verify your webhook URL is correct and accessible
  2. Check the FiveM server console for error messages
  3. Ensure the webhook is subscribed to the correct events
  4. Verify that the event is actually being triggered in the application