BizKitHub
DocsAPI ReferenceActivity/api/v1/customer/add-activity
postActivityPublic API v1

/api/v1/customer/add-activity

Writes one row to core__activity for this organisation. Designed for external applications (e.g. gymroom, bandzone, cctv) that want to centralise their audit log into the BKH platform without re-implementing a per-tenant store. Returns the 24-char public activity id.

Target contact is resolved from identityId (preferred) or customerEmail; a missing e-mail-bearing contact is created on-the-fly (no welcome mail, no password) so follow-up events for the same person land on the same row.

Actor defaults to kind = "api". Use kind = "contact" + email/identityId when the event is attributable to a specific person; kind = "system" | "cron" for unattended work.

Geo attribution: pass customerRealIp to attach the caller's geo footprint; omit it to let the server use the HTTP request's own IP (typically the integration server, not the end-user).

ActivitypostApiV1CustomerAdd-activity

Parameters

1 query · JSON body

Query parameters

· 1
apiKeystringRequired

Your BizKitHub API key (passed as GET parameter).

Key format: A 32-character string matching: ^(PROD|DEV_|ROOT)[A-Za-z0-9]{28}$
Prefixes: PROD (production key), DEV_ (individual developer), ROOT (system key with no limits). Learn more

ExamplePRODPGrFxpGEtrOZfuWhnoJohUYBXuOE

Request body

application/json
eventTypestringRequired

Stable machine-readable event identifier. Convention: {entity}.{verb} dot-notation, lowercase slug with letters, digits, dots, dashes, underscores. Max 64 chars. Examples: bandzone.band.created, gymroom.booking.cancelled, account.password_reset.

Length: 1–64
Examplebandzone.band.created
messagestringRequired

Pre-rendered human-readable one-line summary shown in the admin activity grid. Format in the actor's locale on your side — the audit log does not re-render from a template.

Length: 1–500
ExampleNová kapela "Solární sovy" byla vytvořena uživatelem [email protected].
level"info" | "notice" | "warning"Optional

Severity. info (default) for the vast majority of events, notice for the ones worth highlighting in admin, warning when an operator should look. error is intentionally not offered here — operational errors belong on core__system_log, not the audit feed.

customerEmailstringOptional

E-mail of the TARGET contact (whom the event concerns). Resolved against shop__contact in this organisation; a missing contact is created on-the-fly as a bare record (no welcome e-mail, no password). Leave empty when the event is not tied to a specific person (system-wide events) and set actor.kind = "api" | "system" | "cron".

identityIdstringOptional

Logged user identity (from your frontend cookies). Learn more

ExampleZ9CPkS2o3UV163VQn5OUv0T8BQi8Fvdg
actorobjectOptional
kind"contact" | "system" | "cron" | "api" | "member"Required

Who performed the action. Default api (= the external integration itself). contact requires email or identityId to resolve. member is NOT accepted on the public API — log member actions through BFF.

emailstringOptional

Actor contact e-mail — used when kind = "contact" to resolve actor_contact_id.

identityIdstringOptional

Actor identity id — preferred over email when both are provided. Used when kind = "contact" to resolve actor_contact_id.

correlationIdstringOptional

Opaque correlation token for grouping related events across multiple requests (e.g. a multi-step registration). Max 36 chars. Omit to let the server derive one from the request.

Length: 0–36
Examplebnd-register-01HJ...
metaobjectOptional

Free-form JSON payload stored verbatim on the audit row. Hard cap: 32 KB after serialization — larger payloads are rejected. BigInt values are coerced to Number (or string if out of safe range) because jsonb cannot encode BigInt. Keep the shape stable per eventType — the admin grid relies on it.

occurredAtstringOptional

ACCEPTED FOR COMPATIBILITY BUT IGNORED. The audit row's timestamp is server-side (NOW()); client-reported timestamps cannot be trusted in an audit log. Put the original timestamp into meta.occurredAt if you need to preserve it.

customerRealIpstringOptional

User IP address used for GEO/IP intelligence.

Accepted formats:

  • IPv4 dot-decimal, e.g. 1.1.1.1 (4 octets, 0–255, no leading zeros).
  • IPv6 as defined by RFC 4291 — full 2001:0db8:0000:0000:0000:0000:0000:0001, zero-compressed 2001:db8::1, IPv4-mapped ::ffff:1.2.3.4, or scoped literals. Both upper- and lower-case hex are accepted.

Server-side canonicalization (ipNormalize in core/src/lib/network/ipNormalize.ts):

  • Valid IPv4 is passed through verbatim.
  • Valid IPv6 is lowercased (RFC 5952 §4.3).
  • IPv4-mapped IPv6 ::ffff:X.X.X.X is unwrapped to plain IPv4 (RFC 4291 §2.5.5.2) so 1.2.3.4 and ::ffff:1.2.3.4 share one brj__geo_ip row.
  • Loopback aliases (::1, 0.0.0.0, localhost, empty string) collapse to 127.0.0.1.
  • Junk values that fail both IPv4 and IPv6 validation are silently rejected and replaced with 127.0.0.1 (loopback).

On the wire: every response returns the canonicalized form — clients can safely rely on lowercase IPv6 and the plain-IPv4 unwrap when de-duping or joining. Server-originated writers (activity log, session log, ban list) resolve the visitor IP via resolveClientIp / resolveClientIpOrNull — always native IPv6 on Vercel Edge (there is no auto-mapping to ::ffff:X.X.X.X).

Enrichment: the system resolves reverse DNS, geolocation, ASN, mobile/proxy/hosting/Tor flags via our VikiTron GEO/IP resolver for both address families. Learn more

Examples1.1.1.12001:4860:4860::8888

Response schema

1 status code documented

200Success
object | object
One of 2:
Variant 1
success"true"Required
activityIdstringRequired

24-char public id of the inserted audit row (core__activity.external_id).

Length: 24–24
ExampleaQ9kZxB2fWpL7mYrT3nX8dCv
Variant 2
success"false"Required
errorCodestringRequired

Stable short code for programmatic branching. Known values: INVALID_EVENT_TYPE, INVALID_MESSAGE, META_TOO_LARGE, INVALID_META, ACTOR_MEMBER_UNSUPPORTED, ACTOR_CONTACT_UNRESOLVED, ACTIVITY_WRITE_FAILED.

messagestringRequired

Human-readable error for the integration developer.

Response example

application/json
{
  "success": true,
  "activityId": "aQ9kZxB2fWpL7mYrT3nX8dCv"
}

Request example

POST /api/v1/customer/add-activity

post
curl -X POST "https://api.bizkithub.com/api/v1/customer/add-activity?apiKey=PRODPGrFxpGEtrOZfuWhnoJohUYBXuOE" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -d '{
  "eventType": "bandzone.band.created",
  "message": "Nová kapela \"Solární sovy\" byla vytvořena uživatelem [email protected].",
  "customerEmail": "[email protected]",
  "identityId": "Z9CPkS2o3UV163VQn5OUv0T8BQi8Fvdg",
  "actor": {
    "email": "example_email",
    "identityId": "example_identityId"
  },
  "correlationId": "bnd-register-01HJ...",
  "meta": {},
  "occurredAt": "example_occurredAt",
  "customerRealIp": "1.1.1.1"
}'

Need an API key?

All BizKitHub public API endpoints require authentication via API key.

Get API Key