Activity Logs

11 vues Markdown

The eleven endpoints that read and clear sent messages, sign-ins, actions and module exchanges.

Overview

These eleven endpoints read and clear the books of what the system did: e-mails and messages sent, sign-ins, user actions, what modules exchanged with providers, and database queries.

E-mail and message bodies are stored encrypted and do not come back in the list; a separate endpoint decodes them. The other books read plainly.

Every clear shares one shape: you give a cut-off date and everything on and before it goes. The one exception is the query log, which is file-based and takes no date.

Reference

Listing the E-mail Log

get/api/v1/admin/tools/logs/mail
Tools/GetMailLogs admin paged

Returns the record of e-mails sent. The body is not in the list.

Query parameters 3
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the records.
Response fields data[] — 9
idintId of the record.
user_idintId of the client the mail went to. Zero when the mail was not tied to an account.
reasonstringThe notification key that produced the mail.
subjectstringThe mail subject.
addressesstringThe recipient address or addresses.
datastringThe template variables, serialised.
ipstringThe address the send was triggered from.
privateintOne when the body is withheld from the panel.
ctimestringWhen it was sent, as YYYY-MM-DD HH:MM:SS. The body field is not among these; the list stays light because bodies are large.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/tools/logs/mail' \
  -H "Authorization: Bearer $API_KEY" \
  -d limit=50
const url = new URL('https://panel.example.com/api/v1/admin/tools/logs/mail');
url.searchParams.set('limit', '50');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/tools/logs/mail?' . http_build_query(['limit' => 50]);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The body is stored encrypted and is NOT in the list; you get it from the decode endpoint.
$logs = Api::Tools()->GetMailLogs([], ['limit' => 50])['data'];

$content = Api::Tools()->GetLogPreview(['type' => 'mail', 'id' => $logs[0]['id']]);

Clearing the E-mail Log

delete/api/v1/admin/tools/logs/mail
Tools/ClearMailLogs admin cannot be undone

Deletes e-mail records older than the date you give.

Body 1
beforestringrequiredThe cut-off date. Records on and before it are deleted.
Response fields data — 2
clearedboolWhether the clear ran.
beforestringThe cut-off date that was used.
Errors 2
invalid_date422No valid date was given.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/logs/mail' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"before":"2026-01-01"}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/mail', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ before: '2026-01-01' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/mail');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['before' => '2026-01-01']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The response does not say HOW MANY were deleted; count them by listing first.
Api::Tools()->ClearMailLogs(['before' => '2026-01-01']);

Listing the SMS Log

get/api/v1/admin/tools/logs/sms
Tools/GetSmsLogs admin paged

Returns the record of text messages sent. The body is not in the list.

Query parameters 3
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the records.
Response fields data[] — 11
idintId of the record.
user_idintId of the client the message went to. Zero when it was not tied to an account.
reasonstringThe notification key that produced the message.
titlestringThe message title.
numbersstringThe recipient number or numbers.
datastringThe template variables, serialised.
ipstringThe address the send was triggered from.
privateintOne when the body is withheld from the panel.
ownerstringThe sending side: admin or client.
owner_idintThe account that triggered the send.
ctimestringWhen it was sent, as YYYY-MM-DD HH:MM:SS. The body field is missing here for the same reason as the e-mail log.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/tools/logs/sms' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/tools/logs/sms', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/sms');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Tools()->GetSmsLogs();

Clearing the SMS Log

delete/api/v1/admin/tools/logs/sms
Tools/ClearSmsLogs admin cannot be undone

Deletes text message records older than the date you give.

Body 1
beforestringrequiredThe cut-off date. Records on and before it are deleted.
Response fields data — 2
clearedboolWhether the clear ran.
beforestringThe cut-off date that was used.
Errors 2
invalid_date422No valid date was given.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/logs/sms' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"before":"2026-01-01"}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/sms', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ before: '2026-01-01' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/sms');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['before' => '2026-01-01']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
Api::Tools()->ClearSmsLogs(['before' => '2026-01-01']);

Listing the Sign-in Log

get/api/v1/admin/tools/logs/login
Tools/GetLoginLogs admin paged

Returns the record of sign-ins to the panel and the client area.

Query parameters 4
typestringWhich side: client or admin. It defaults to client; staff sign-ins are the admin side and have to be asked for by that name.
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the records.
Response fields data[] — 15
idintId of the sign-in record.
owner_idintThe account the sign-in belongs to.
user_idintThe same account, from the joined client row.
full_namestringThe account holder's name.
company_namestringThe company name on corporate accounts.
blacklistintOne when the account is blacklisted.
ipstringThe address the sign-in came from.
portstringThe source port.
country_codestringThe ISO country code resolved from the address.
citystringThe city resolved from the address.
latlngstringThe latitude and longitude resolved from the address.
timezonestringThe time zone resolved from the address.
user_agentstringThe browser user agent.
tokenstringThe session token tied to the sign-in.
ctimestringWhen the sign-in happened, as YYYY-MM-DD HH:MM:SS. The type filter works on the joined account, so a record always belongs to one side or the other.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/tools/logs/login' \
  -H "Authorization: Bearer $API_KEY" \
  -d type=admin
const url = new URL('https://panel.example.com/api/v1/admin/tools/logs/login');
url.searchParams.set('type', 'admin');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/tools/logs/login?' . http_build_query(['type' => 'admin']);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// Without a type you get CLIENT sign-ins; staff sign-ins answer to 'admin', not 'staff'.
$staff = Api::Tools()->GetLoginLogs([], ['type' => 'admin']);

Listing the Action Log

get/api/v1/admin/tools/logs/actions
Tools/GetActionLogs admin paged

Returns the record of what users and the system did.

Query parameters 4
typestringWhose actions: client, admin or system. It defaults to client.
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the records.
Response fields data[] — 9
idintId of the record.
owner_idintThe account that performed the action.
target_idintThe record the action was performed on.
reasonstringThe action group: update, deletion, create and the like.
detailstringThe action key. A translation key from the action language file, not a sentence: resolve it there rather than showing it raw.
locale_detailstringReadable text, when the writer supplied one. Your fallback when the key cannot be resolved.
datastringThe context of the action, serialised.
ipstringThe address the action came from.
ctimestringWhen it happened, as YYYY-MM-DD HH:MM:SS. Module records share this table but stay out of this listing; they have their own endpoint.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl -G 'https://panel.example.com/api/v1/admin/tools/logs/actions' \
  -H "Authorization: Bearer $API_KEY" \
  -d type=admin
const url = new URL('https://panel.example.com/api/v1/admin/tools/logs/actions');
url.searchParams.set('type', 'admin');

const res  = await fetch(url, { headers: { Authorization: `Bearer ${apiKey}` } });
const body = await res.json();
$url = 'https://panel.example.com/api/v1/admin/tools/logs/actions?' . http_build_query(['type' => 'admin']);

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
$response = Api::Tools()->GetActionLogs([], ['type' => 'admin']);

Clearing the Action Log

delete/api/v1/admin/tools/logs/actions
Tools/ClearActionLogs admin cannot be undone

Deletes action records older than the date you give. It leaves the module log alone.

Body 1
beforestringrequiredThe cut-off date. Records on and before it are deleted.
Response fields data — 2
clearedboolWhether the clear ran.
beforestringThe cut-off date that was used.
Errors 2
invalid_date422No valid date was given.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/logs/actions' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"before":"2026-01-01"}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/actions', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ before: '2026-01-01' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/actions');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['before' => '2026-01-01']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// This clear does NOT sweep the module log; that has its own endpoint.
Api::Tools()->ClearActionLogs(['before' => '2026-01-01']);
Api::Tools()->ClearModuleLogs(['before' => '2026-01-01']);

Listing the Module Log

get/api/v1/admin/tools/logs/module
Tools/GetModuleLogs admin paged

Returns the record of what modules exchanged with providers.

Query parameters 3
pageintDefaults to 1.
limitintDefaults to 25, maximum 100.
searchstringSearches the records.
Response fields data[] — 9
idintId of the record.
owner_idintThe account tied to the call. Zero when the system triggered it.
target_idintThe service the module call belonged to.
reasonstringAlways module-log on this endpoint.
detailstringThe module and the action recorded.
locale_detailstringReadable text, when the writer supplied one.
datastringThe request and answer of the module call, serialised.
ipstringThe address the call came from.
ctimestringWhen it happened, as YYYY-MM-DD HH:MM:SS. These records share a table with the action log, but clearing one leaves the other untouched.
Meta 4
totalintTotal records matching the filter.
pageintThe page you are on.
limitintThe page size.
next_pageintThe next page. Zero means you are on the last one.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl 'https://panel.example.com/api/v1/admin/tools/logs/module' \
  -H "Authorization: Bearer $API_KEY"
const res  = await fetch('https://panel.example.com/api/v1/admin/tools/logs/module', {
  headers: { Authorization: `Bearer ${apiKey}` },
});
const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/module');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The module log only fills while it is ON in the log settings; an empty list is not 'all fine'.
$settings = Api::Tools()->GetLogSettings()['data'];

if ($settings['module_log']) {
    $logs = Api::Tools()->GetModuleLogs();
}

Clearing the Module Log

delete/api/v1/admin/tools/logs/module
Tools/ClearModuleLogs admin cannot be undone

Deletes module records older than the date you give.

Body 1
beforestringrequiredThe cut-off date. Records on and before it are deleted.
Response fields data — 2
clearedboolWhether the clear ran.
beforestringThe cut-off date that was used.
Errors 2
invalid_date422No valid date was given.
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/logs/module' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"before":"2026-01-01"}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/module', {
  method: 'DELETE',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ before: '2026-01-01' }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/module');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['before' => '2026-01-01']),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
Api::Tools()->ClearModuleLogs(['before' => '2026-01-01']);

Decoding the Body

post/api/v1/admin/tools/logs/preview
Tools/GetLogPreview admin decrypts

Decrypts and returns the stored body of one e-mail or text message record.

Body 2
typestringrequiredWhich log: mail or sms.
idintrequiredId of the record.
Response fields data — 3
typestringThe log type.
idintId of the record.
contentstringThe decrypted body. The very text that went to the client.
Errors 3
invalid_request422The type or the id was missing.
not_found404No such record.
insufficient_scope403The key lacks the required scope.
Request
curl -X POST 'https://panel.example.com/api/v1/admin/tools/logs/preview' \
  -H "Authorization: Bearer $API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{"type":"mail","id":1240}'
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/preview', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${apiKey}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ type: 'mail', id: 1240 }),
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/preview');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_HTTPHEADER     => [
        'Authorization: Bearer ' . $apiKey,
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode(['type' => 'mail', 'id' => 1240]),
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// The decrypted body carries client data: do not write it to your own logs.
$content = Api::Tools()->GetLogPreview([
    'type' => 'mail',
    'id'   => 1240,
])['data']['content'];

Deleting the Query Log

delete/api/v1/admin/tools/logs/query
Tools/ClearQueryLogs admin deletes files

Deletes the database query log files. It takes no date and removes all of them.

Response fields data — 2
clearedboolWhether the clear ran.
deletedintHow many files were deleted.
Errors 1
insufficient_scope403The key lacks the required scope.
Request
curl -X DELETE 'https://panel.example.com/api/v1/admin/tools/logs/query' \
  -H "Authorization: Bearer $API_KEY"
const res = await fetch('https://panel.example.com/api/v1/admin/tools/logs/query', {
  method: 'DELETE',
  headers: { Authorization: `Bearer ${apiKey}` },
});

const body = await res.json();
$ch = curl_init('https://panel.example.com/api/v1/admin/tools/logs/query');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_CUSTOMREQUEST  => 'DELETE',
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . $apiKey],
]);

$body = json_decode(curl_exec($ch), true);
curl_close($ch);
// This endpoint takes NO date: every file goes. Writing them is switched off in the settings.
Api::Tools()->ClearQueryLogs();
Api::Tools()->SetLogSettings(['query_logging' => 0]);

Pitfalls

The body is not in the list

The content of e-mail and message records is stored encrypted and never comes back from the listing endpoints. Seeing what was sent means calling the decode endpoint separately, one request per record. The decrypted text carries client data, so do not store it on your side.

An empty book does not mean nothing happened

The module and query logs only fill while they are on in the log settings. With them off the lists come back empty, which does not mean nothing happened. Confirm in the settings that the log you need is on before investigating anything.

The default side is the client

On the sign-in and action logs, leaving the type out gives you the client side. Looking for admin sign-ins or the system's own actions means sending the type explicitly, or you conclude the record you want never existed.

The action clear leaves the module log

Clearing the action log leaves the module log where it is; they are separate endpoints. Making one call to free space, you may not notice the bigger book is still sitting there.

The clear does not say how many it deleted

The date-based clears return only that they ran and which date they used; they give no count. To measure the effect, list the same range and count it first.

Cet article vous a-t-il été utile ?

Merci pour votre retour !

Besoin d'aide supplémentaire ?

Notre équipe d'assistance est disponible 24h/24 pour tout ce que vous ne trouvez pas ci-dessus.