Custom activities#
A custom activity records an action in your referral program that Talkable can’t see on its own. For example, a person opens a screen in your app, taps a button, or finishes a step on your backend. You send each activity with one API call. Talkable stores it with the person, the time, and the offer, if you link one. The Custom Activities report lists the activities, so you can compare how many people reach each one. See Track a custom activity in the API reference.
How custom activities work#
Each custom activity has a name, called a key. An activity sent through the API belongs to one person. When you send the Advocate’s offer code with the activity, Talkable links it to that offer and copies its campaign and traffic source. An activity can also happen before the person has an offer, for example on the screen that shows your referral entry point.
You can send activities from three places:
Your backend — with the API key, for actions on your server, such as a completed profile.
Your mobile app — with the Public API key, for actions in the app.
A Talkable campaign page — with the page script, for actions on the Advocate share page or the Friend Claim Page.
For example, an app can track the steps of its referral screen:
Key |
When the app sends it |
|---|---|
|
The screen with the referral entry point is shown |
|
The user taps the referral entry point |
|
The referral screen is shown |
|
The user copies the link or picks an app to share |
|
The user opens the contacts list |
|
The user invites contacts, with their number in |
Name your activities#
A key has 3 to 50 characters: lowercase letters and numbers, with single underscores between words. It starts with a letter and doesn’t end with an underscore. A site can have up to 50 keys.
A call with the private API key registers a new key on first use. Keys stay
registered. Choose them before your release, and send them exactly as written.
Put extra detail, such as the platform or app version, in properties.
Send an activity#
Send each activity to the person’s endpoint, with the site in the query string:
curl -X POST \
'https://www.talkable.com/api/v2/people/jane%40example.com/custom_activities?site_slug=example-site' \
-H 'Authorization: Bearer YOUR_API_KEY' \
-H 'Content-Type: application/json' \
-d '{
"data": {
"key": "contacts_invited",
"idempotency_key": "c2e8d1f4-9a3b-4e6c-8d7f-1b5a9c3e2f60",
"offer_short_url_code": "a1B2c3",
"quantity": 3,
"properties": {"platform": "ios", "app_version": "5.2.0"}
}
}'
Identify the person who took the action by their email, URL-encoded in the path. For an Advocate, use the email from their offer. A new email creates the person, unless your site identifies people by phone number. With the private API key, you can also use a customer ID, phone number, or username.
Field |
Use |
|---|---|
|
Required. The activity’s key |
|
Required. Your ID for this activity, 1 to 255 printable ASCII characters, for example a UUID |
|
The Advocate’s offer. Links the activity to the offer and its campaign |
|
The Friend’s offer, for an activity on the Friend’s side. The
default destination URL carries it as |
|
The campaign, for an activity before the person has an offer |
|
|
|
A whole number from 1 to 10,000. The default is 1 |
|
For share actions: |
|
When the action happened, in ISO 8601 with |
|
A flat object of strings, numbers, booleans, or nulls, up to 2 KB as JSON. No personal data |
Send at most one of offer_short_url_code, visitor_offer_id, and
campaign_id. Any field not listed in the API reference is refused.
A recorded activity returns 201 with the stored activity:
{
"ok": true,
"result": {
"custom_activity": {
"id": 97,
"key": "contacts_invited",
"quantity": 3,
"role": "advocate",
"offer_short_url_code": "a1B2c3",
"visitor_offer_id": null,
"campaign_id": 3703,
"sharing_channel": null,
"properties": {"platform": "ios", "app_version": "5.2.0"},
"created_at": "2026-10-30T05:26:59.000-07:00"
}
}
}
Retry safely#
Create a new idempotency_key for each action, including repeats of the same
action. To retry a call that failed or timed out, send it again
with the same API key, idempotency_key, and data. Talkable answers 201
with the stored activity and records it once. The same idempotency_key with
different data returns 400.
Activities sent later, for example after the app was offline, carry the time
of the action in occurred_at.
From a mobile app#
An app can send activities directly with the Public API key. These calls follow a few extra rules:
Only keys that are already registered are accepted. Register a new key once with the private API key, from your backend.
Identify the person by email, customer ID, or phone number.
Use a random
idempotency_key, such as a UUID.A site accepts up to 20,000 of these calls a day from one IP address, retries included. Further calls return
429.
The report shows these activities with the source Mobile app. Activities sent with the private API key show the source API.
From a campaign page#
A Talkable campaign page, such as the Advocate share page or the Friend Claim Page, can record an activity with the page script:
Talkable.trackCustomActivity('share_action_taken', {
sharing_channel: 'other'
}, onSuccess, onError);
The page script takes quantity, sharing_channel, properties, and
idempotency_key. It accepts only registered keys. It uses the offer on the
page, and the person if the page knows them. The report shows
these activities with the source Page script.
Review activities#
The Custom Activities report lists every recorded activity, in All reports under Support. Filter by period, key, person, role, source, or campaign, and export the rows as CSV. The optional QA column marks QA activities. Users with the Read role and above can open the report.
Errors#
An API call with invalid data returns 400 with
{"ok": false, "error_message": "..."}. The message names the problem:
Message includes |
What to change |
|---|---|
|
Remove a field the endpoint doesn’t take |
|
Register the key with the private API key first |
|
Fix the key’s format |
|
Use a new |
|
Send a time from the last 7 days and at most 5 minutes ahead, or leave it out |
|
Check the offer code and the site |
|
Send the email of the offer’s owner |
A read-only API key returns 401. A public-key call over the daily limit
returns 429.
Next steps#
Referral program via API: the full flow, from the Advocate’s offer to the Friend’s purchase.
Origins: report purchases and events.