Village Product and Developer Docs
  • 📘Welcome to Village Labs
    • Welcome to Village Labs
    • Self Service Onboarding
    • Help Pages
      • Adding and Deleting Users
      • Mapping Users to Source tool IDs
      • How to follow or unfollow other users
      • Configuring & Removing Daily Slack Notification Whitelist
      • Changing the Reporting Lines & Teams
      • Following Custom Reports
      • Google Drive Privacy: When will my documents appear in Village Reports?
    • Custom Reports
      • Creating Team Reports
      • Creating Custom Reports & Custom Prompt Library
    • Meetings
      • Connecting your Calendar
      • Configuring your Meetings
      • Meeting Summary Reports
    • Village Assistant
      • Github PR Review Tool
    • Security & Compliance
    • Data Privacy & Permissions
  • 🔌Data Connections
    • Airtable
    • Ashby
    • Clickup
      • Finding ClickUp User IDs
    • Figma
    • Github
      • Finding GitHub User IDs
    • Gitlab
    • Google - OAuth (Recommended)
    • Google - Manual Connection
    • Hubspot
    • Jira
      • Finding Jira User IDs
    • Confluence
      • Finding Confluence / Jira User IDs
    • Linear
    • Asana
    • Monday
    • Notion
    • Pipedrive
    • Slack
    • Basecamp
    • Zoom
  • 👩‍💻Legacy Developer Docs
    • Developer Quickstart
    • Village APIs: Introduction
      • Activity API
      • User Status API
      • Patch User API
      • Segments API
      • Redemption API
      • Master Award Controls
      • Connections (Referrals) APIs
      • GET APIs
    • 3rd Party Payments Integrations
    • Embedding Village Dashboards
  • 🕵️LEGACY Knowledge Base
    • Admin Quickstart
    • Referrals Support
    • The Basics of Village in 15 Minutes
    • Programs & Rules
      • Triggers
        • Activities
        • Goals
      • Conditions
        • Segment Conditions
        • Time Conditions
        • Max Budget Conditions
        • Conditional Multipliers
    • Awards
      • Monetary (Cash) Awards
      • Non-Monetary Awards
        • Funding
          • In-depth use cases for funding pools
      • Badges & Statuses
      • Award Expiration
    • Segments
      • Segmentation Use Cases
    • Rule Evaluation Logic Deep-dive
    • The Village Dashboards
      • Admin Account Creation
      • User Access Management
      • Network Settings
      • User Dashboard
    • BigQuery
    • Managing Payment Integrations
    • Referrals (Connections)
      • Pre-populating Users' Unique Referral Codes In Signup Flows & Forms
  • No and Low Code Solutions
    • No and Low Code Solutions
      • No & Low Code Solutions
  • Feedback
    • Village Docs Feedback Form
    • Feature Requests
    • Talk to our Team
Powered by GitBook
On this page
  • About the Activity API
  • Defining Activities
  • Endpoint
  • API Field Overview
  • Body Fields
  • Metadata
  • Examples
  • Body
  • By Language

Was this helpful?

  1. Legacy Developer Docs
  2. Village APIs: Introduction

Activity API

PreviousVillage APIs: IntroductionNextUser Status API

Last updated 1 year ago

Was this helpful?

About the Activity API

The Activity API is Village's most commonly used API.

An “Activity” represents something your users do. It is the a basic unit of data that can represent any sort of user activity both online and in the real world. Activities can be anything from completing a transaction, clicking a button, or making a delivery.

Activities are the foundation of most Rule logic. Even with a relatively small number of Activities, you can build incredibly powerful and intricate incentive & segmentation system.

We recommend that you log as many Activity types that you can up front to reduce maintenance effort (see Guides->).

Defining Activities

You can send Activities to the Activity API to be logged on the Village ledger (making them queryable) without adding them first on the Admin Dashboard.

However, until they are added, they will not be usable in Program & Rule logic.

To be used in logic, Activities must be added in the Admin Dashboard -> Incentives -> Triggers -> Actions/Sales. Any Admin can complete this action.

If an Activity is sent through the Activity API without having been defined on the Admin Dashboard, it will still be logged on the Village ledger (and therefore queryable in the future). It will not be usable in Program & Rule logic until it is added, however.

Note there are two types of Activities: Actions and Sales (learn more ). However the Activity API is agnostic to the type; any logic based on Actions or Sales will be based on the Activity Short ID field.

Endpoint

POST/networks/YOUR_NETWORK_ID/activity

Where 'YOUR_NETWORK_ID' is replaced with your actual Network ID.

API Field Overview

Every Activity has an amount field, in which you can report the volume of activities (example: 1 checkout, 3 deliveries, 4.45 hours) or the degree of an activity (example: 5 star rating, 3 star rating).

When Activities are created as Actions and Sales, they can reference multiple users and include metadata for tracking and reporting.

Pay attention to the amount field: most of the time, the amount field is going to be set to 1, since 1 event or activity of that type occurred. If you have a rule in Village that pays $50 when a task is completed, the rule will multiply the task activity amount (1) by $50 to calculate the payout. In this case, if you entered 50 in the activity amount field, this would result in a payout of 50 * $50 = $2500!

The exception to this rule is when you are configuring sales triggers. In this case, the amount field should be the total amount of the transaction or sale, eg. 500 if it was a $500 sale. For example, if a rule pays 1% cash back on each sale, it would multiply the rule amount field (.01) by the sales activity amount field ($500) to get a cash back of $5 for that sale.

Body Fields

Field Name
JSON Key
Type
Description
Required

Activity Short ID

activity_short_id

string

CASE SENSITIVE. A short identifier for the activity. This will match either the Action ID or Sale ID that was set when the Action on Sale trigger type was created.

Yes

Amount

amount

string

The activity amount. For Actions, this is the number of actions. For Sales, this is the sale transaction amount.

Yes

Associated Users

users

map

List of users involved in the activity. This map has two parts, first is one of the pre-set "Associated Users" from the Trigger (e.g. "seller") and the second is the email associated with their Village account (e.g. "bradford@villagelabs.co"). At least one Associated User is required to be submitted with every Activity.

Yes

Metadata

metadata

object

Additional metadata for the activity. See Metadata fields for options.

No

About Associated Users

Metadata

Field Name
JSON Key
Type
Description
Required

Reference ID

reference_id

string

An optional identifier that can be used for reporting purposes.

No

Activity Timestamp

activity_timestamp

integer

The Unix timestamp of when the activity occurred (in seconds, not milliseconds). If this is blank, Village will use the timestamp the activity was received via the Village API as the Activity Timestamp.

No

Description

description

string

A description of the activity.

No

Enforce Unique Ref ID

enforceUniqueRefId

boolean

Enforces a unique reference ID to process Activities.

Examples

Body

Critical note: The activity_short_id is case sensitive, and must exactly match the Trigger created on the dashboard in order to be processed.

// Example Activity Body
// activity_short_id is case sensitive
// User emails must already exist in Village system to be accepted
// activity_timestamp is Unix timestamp in seconds, not milliseconds

{
    "activity_short_id": "sale", 
    "amount": "3",
    "users": {
        "buyer": "bradford@theroutingcompany.com", 
        "seller": "bradford@villagelabs.co"
    },
    "metadata": {
        "reference_id": "customer_ref_id",
        "activity_timestamp": 12345678910, // Epoch time in seconds 
        "description": "customer description"
    },
    "enforceUniqueRefId": false, // Enforces the the reference_id to be unique, and does not process requests that aren't unique. There is no error message when this activates
}

By Language

#Remember to replace 'YOUR_API_KEY' with your actual API key
#Replace 'YOUR_NETWORK_ID' with your actual network ID

import requests
import json

# Define the URL of the User Status API
url = "https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity"

# Define the headers for the API request
headers = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY' 
}

# Define the data for the API request
data = {
    "activity_short_id": "S1-A",
    "amount": "100.99",
    "users": {
        "seller": "john.buyer@villagelabs.co",
        "buyer": "jane.seller@villagelabs.co"
    },
    "metadata": {
        "reference_id": "dpi_Ylo2Cfr8US8u1JIdAl2eZvKB",
        "activity_timestamp": 1664900628,
        "description": "Especially fancy white shoes."
    }
}

# Convert the data to JSON format
data_json = json.dumps(data)

# Send the request to the API
response = requests.post(url, headers=headers, data=data_json)

# Check the response from the API
if response.status_code == 201:
    print("Successfully sent activity data to the API.")
elif response.status_code == 400:
    print("Bad request. Please check the data you are sending to the API.")
elif response.status_code == 401:
    print("Unauthorized. Please check your API key.")
elif response.status_code == 404:
    print("API not found. Please check your API url.")
elif response.status_code == 500:
    print("Internal Server Error. Please try again later.")
else:
    print(f"Received unexpected status code {response.status_code}.")
    
//Remember to replace 'YOUR_API_KEY' with your actual API key
//Replace 'YOUR_NETWORK_ID' with your actual network ID

// Define the URL of the Activity API
let url = "https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity";

// Define the headers for the API request
let headers = {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
    'Authorization': 'Bearer YOUR_API_KEY'  
};

// Define the data for the API request
let data = {
    "activity_short_id": "S1-A",
    "amount": "100.99",
    "users": {
        "seller": "john.buyer@villagelabs.co",
        "buyer": "jane.seller@villagelabs.co"
    },
    "metadata": {
        "reference_id": "dpi_Ylo2Cfr8US8u1JIdAl2eZvKB",
        "activity_timestamp": 1664900628,
        "description": "Especially fancy white shoes."
    }
};

// Send the request to the API
fetch(url, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify(data)  // JavaScript has JSON.stringify() to convert object into JSON
})
.then(response => {
    switch(response.status) {
        case 201:
            console.log("Successfully sent activity data to the API.");
            break;
        case 400:
            console.log("Bad request. Please check the data you are sending to the API.");
            break;
        case 401:
            console.log("Unauthorized. Please check your API key.");
            break;
        case 404:
            console.log("API not found. Please check your API url.");
            break;
        case 500:
            console.log("Internal Server Error. Please try again later.");
            break;
        default:
            console.log(`Received unexpected status code ${response.status}.`);
    }
})
.catch(error => console.error('Error:', error));
//Remember to replace 'YOUR_API_KEY' with your actual API key
//Replace 'YOUR_NETWORK_ID' with your actual network ID

curl -X POST https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
    "activity_short_id": "S1-A",
    "amount": "100.99",
    "users": {
        "seller": "john.buyer@villagelabs.co",
        "buyer": "jane.seller@villagelabs.co"
    },
    "metadata": {
        "reference_id": "dpi_Ylo2Cfr8US8u1JIdAl2eZvKB",
        "activity_timestamp": 1664900628,
        "description": "Especially fancy white shoes."
    }
}'
#Remember to replace 'YOUR_API_KEY' with your actual API key
#Replace 'YOUR_NETWORK_ID' with your actual network ID

require 'net/http'
require 'uri'
require 'json'

# Define the URL of the Activity API
uri = URI.parse("https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity")

# Define the headers for the API request
headers = {
    'Content-Type' => 'application/json',
    'Accept' => 'application/json',
    'Authorization' => 'Bearer YOUR_API_KEY'  # Replace 'Bearer YOUR_API_KEY' with your actual API key
}

# Define the data for the API request
data = {
    "activity_short_id" => "S1-A",
    "amount" => "100.99",
    "users" => {
        "seller" => "john.buyer@villagelabs.co",
        "buyer" => "jane.seller@villagelabs.co"
    },
    "metadata" => {
        "reference_id" => "dpi_Ylo2Cfr8US8u1JIdAl2eZvKB",
        "activity_timestamp" => 1664900628,
        "description" => "Especially fancy white shoes."
    }
}

# Create a new HTTP request with the headers, data and URL
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri, headers)
request.body = data.to_json

# Send the request and capture the response
response = http.request(request)

# Check the response from the API
case response.code.to_i
when 201
  puts "Successfully sent activity data to the API."
when 400
  puts "Bad request. Please check the data you are sending to the API."
when 401
  puts "Unauthorized. Please check your API key."
when 404
  puts "API not found. Please check your API url."
when 500
  puts "Internal Server Error. Please try again later."
else
  puts "Received unexpected status code #{response.code}."
end
//Remember to replace 'YOUR_API_KEY' with your actual API key
//Replace 'YOUR_NETWORK_ID' with your actual network ID

import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws Exception {
        String url = "https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity";
        URL obj = new URL(url);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod("POST");

        //add request header
        con.setRequestProperty("Content-Type", "application/json");
        con.setRequestProperty("Accept", "application/json");
        con.setRequestProperty("Authorization", "Bearer YOUR_API_KEY");

        String data = "{\"activity_short_id\":\"S1-A\",\"amount\":\"100.99\",\"users\":{\"seller\":\"john.buyer@villagelabs.co\",\"buyer\":\"jane.seller@villagelabs.co\"},\"metadata\":{\"reference_id\":\"dpi_Ylo2Cfr8US8u1JIdAl2eZvKB\",\"activity_timestamp\":1664900628,\"description\":\"Especially fancy white shoes.\"}}";

        // Send post request
        con.setDoOutput(true);
        OutputStream os = con.getOutputStream();
        os.write(data.getBytes());
        os.flush();
        os.close();

        int responseCode = con.getResponseCode();
        System.out.println("Response Code : " + responseCode);
    }
}
// Remember to replace 'YOUR_API_KEY' with your actual API key
//Replace 'YOUR_NETWORK_ID' with your actual network ID

package main

import (
	"bytes"
	"net/http"
)

func main() {
	url := "https://api-ledger.villagelabs.net/networks/YOUR_NETWORK_ID/activity"
	var jsonStr = []byte(`{"activity_short_id":"S1-A","amount":"100.99","users":{"seller":"john.buyer@villagelabs.co","buyer":"jane.seller@villagelabs.co"},"metadata":{"reference_id":"dpi_Ylo2Cfr8US8u1JIdAl2eZvKB","activity_timestamp":1664900628,"description":"Especially fancy white shoes."}}`)
	req, _ := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Accept", "application/json")
	req.Header.Set("Authorization", "Bearer YOUR_API_KEY")

	client := &http.Client{}
	resp, _ := client.Do(req)
	defer resp.Body.Close()

	println("response Status:", resp.Status)
}

👩‍💻
Is this page helpful? Give us feedback on our docs ->
Is this page helpful? Give us feedback on our docs ->
Program & Rule
here ->