Siren

Programs

Affiliate programs — data model, status lifecycle, REST API, PHP data access, engagement types, and transaction compilers.

Last updated: April 9, 2026

Programs

A program defines a set of rules for how collaborators earn rewards. Each program specifies an incentive structure (how rewards are calculated), engagement types (what actions trigger attribution), and a currency unit (what the rewards are denominated in). Programs are the central organizing concept in Siren. Collaborators are enrolled in programs, and conversions, obligations, and fulfillments all trace back to the program that governs them.

The program object

FieldREST namePHP getterTypeDescription
IDidgetId()integerUnique identifier
NamenamegetName()stringDisplay name of the program
DescriptiondescriptiongetDescription()stringHuman-readable description of what the program does
Incentive typeincentiveTypegetIncentiveType()stringIncentive type identifier (e.g., commission)
Incentive resolverincentiveResolverTypegetIncentiveResolverType()stringStrategy used to resolve incentive amounts
StatusstatusgetStatus()stringCurrent status: active, inactive, draft, or deleted
UnitsunitsgetUnits()stringCurrency or unit identifier for reward denominations (e.g., USD, points)
CreateddateCreatedgetCreatedDate()datetimeWhen the record was created
ModifieddateModifiedgetModifiedDate()datetimeWhen the record was last updated

Extended fields (REST only, via ?fields=)

These fields are resolved dynamically by the REST API field resolver system and must be explicitly requested:

FieldTypeDescription
collaboratorsarrayList of collaborators enrolled in this program, each with id and nickname
collaboratorCountintegerTotal number of collaborators enrolled in this program
engagementsCountintegerTotal number of engagements associated with this program
engagementTypesarrayEngagement type configurations for this program, each with id, type, and value
transactionCompilersarrayActive transaction compilers for this program, each with id and compiler
incentiveConfigobjectCombined incentive type and resolver metadata, each with id and name
incentiveCalculationobjectIncentive calculation settings including transactionPercent, payoutPerTransaction, payoutPerProduct, payoutPerLead, activeConversionTypes, autoApprove, and leadRequalificationDays
expirationDaysinteger or nullNumber of days before the program’s conversions expire, or null if no expiration is set
lineItemFiltersobject or nullTransaction line item filtering rules including withTypes, collaboratorOwned, withSkus, and inCategories

When extended fields are requested, incentiveType and incentiveResolverType are enriched from plain string identifiers to objects containing both id and name.

Status lifecycle

StatusDescription
activeProgram is live and accepting new engagements and conversions.
inactiveProgram is paused. Existing data is preserved, but new activity is not processed.
deletedSoft-deleted. A second DELETE call permanently removes the record. Bulk restore moves the program back to inactive.

Accessing program data

# List active programs
curl -X GET "https://your-site.com/wp-json/siren/v1/programs?status=active" \
  -H "Authorization: Bearer YOUR_TOKEN"

# Get a single program with extended fields
curl -X GET "https://your-site.com/wp-json/siren/v1/programs/5?fields=id,name,status,collaboratorCount,engagementTypes,incentiveCalculation" \
  -H "Authorization: Bearer YOUR_TOKEN"
use Siren\Programs\Core\Datastores\Program\Interfaces\ProgramDatastore;

class MyService
{
    protected ProgramDatastore $programs;

    public function __construct(ProgramDatastore $programs)
    {
        $this->programs = $programs;
    }

    public function getActivePrograms(): array
    {
        return $this->programs->andWhere([
            ['column' => 'status', 'operator' => '=', 'value' => 'active']
        ]);
    }
}
use Siren\Programs\Core\Facades\Programs;

$activePrograms = Programs::andWhere([
    ['column' => 'status', 'operator' => '=', 'value' => 'active']
]);

$program = Programs::getById(42);

Siren is built on an event-driven architecture. If you find yourself creating programs manually in code, consider whether your use case is better served by the admin UI or the recipe import system. Direct datastore writes bypass the normal event flow and can leave related records out of sync.

PHP domain methods

Looking up a collaborator’s programs

getCollaboratorPrograms retrieves all programs a specific collaborator participates in. This queries the junction table that links collaborators to programs and returns the full program models.

use Siren\Programs\Core\Datastores\Program\Interfaces\ProgramDatastore;

class CollaboratorDashboard
{
    protected ProgramDatastore $programs;

    public function __construct(ProgramDatastore $programs)
    {
        $this->programs = $programs;
    }

    public function listPrograms(int $collaboratorId): array
    {
        // Returns Program[] - defaults to 10 results starting at offset 0
        return $this->programs->getCollaboratorPrograms($collaboratorId);
    }

    public function listAllPrograms(int $collaboratorId): array
    {
        // Paginate with custom limit and offset
        return $this->programs->getCollaboratorPrograms($collaboratorId, 50, 0);
    }
}
use Siren\Programs\Core\Facades\Programs;

// Get first 10 programs for a collaborator
$programs = Programs::getCollaboratorPrograms($collaboratorId);

// With pagination
$programs = Programs::getCollaboratorPrograms($collaboratorId, 25, 0);

Counting collaborators in a program

getCollaboratorCount returns the estimated number of collaborators enrolled in a given program.

$count = $this->programs->getCollaboratorCount($programId);
use Siren\Programs\Core\Facades\Programs;

$count = Programs::getCollaboratorCount($programId);

Engagement types

Each program can be configured with one or more engagement types that define which kinds of engagements are tracked and how they are valued. Engagement types are stored as separate records linked to a program by programId.

The engagement type model (Siren\Programs\Core\Models\ProgramEngagementType) has the following fields:

FieldPHP getterTypeDescription
IDgetId()integerPrimary key
ProgramgetProgramId()integerThe program this engagement type belongs to
Engagement typegetEngagementType()stringType identifier (e.g., saleTransaction, leadCapture)
Engagement valuegetEngagementValue()floatNumeric value or weight assigned to this engagement type

Accessing engagement type data

use Siren\Programs\Core\Datastores\ProgramEngagementTypes\Interfaces\ProgramEngagementTypeDatastore;

class IncentiveCalculator
{
    protected ProgramEngagementTypeDatastore $engagementTypes;

    public function __construct(ProgramEngagementTypeDatastore $engagementTypes)
    {
        $this->engagementTypes = $engagementTypes;
    }

    public function getAllEngagementTypes(int $programId): array
    {
        return $this->engagementTypes->getProgramEngagementTypes($programId);
    }

    public function getSaleValue(int $programId): float
    {
        $type = $this->engagementTypes->getEngagementTypeForProgram(
            $programId,
            'saleTransaction'
        );

        return $type->getEngagementValue();
    }
}
use Siren\Programs\Core\Facades\ProgramEngagementTypes;

// Get all engagement types for a program
$types = ProgramEngagementTypes::getProgramEngagementTypes($programId);

// Get a specific engagement type configuration
// Throws RecordNotFoundException if the program doesn't have this type configured
$saleType = ProgramEngagementTypes::getEngagementTypeForProgram(
    $programId,
    'saleTransaction'
);

$value = $saleType->getEngagementValue();

getProgramEngagementTypes returns all engagement types configured for a program. getEngagementTypeForProgram retrieves a single engagement type by program ID and type identifier, and throws RecordNotFoundException if the combination doesn’t exist.

Transaction compilers

Transaction compilers define how a program calculates transaction amounts. Each program can have one or more compilers registered, and each compiler record links a program to a compiler strategy identifier. For a user-level overview of the built-in filters (line items, discounts, fees, shipping, taxes) and how they’re configured through the admin UI, see Line Item Filters.

The transaction compiler model (Siren\Programs\Core\Models\ProgramTransactionCompiler) has the following fields:

FieldPHP getterTypeDescription
IDgetId()integerPrimary key
ProgramgetProgramId()integerThe program this compiler belongs to
CompilergetTransactionCompiler()stringThe compiler strategy identifier

Accessing transaction compiler data

use Siren\Programs\Core\Datastores\ProgramTransactionCompilers\Interfaces\ProgramTransactionCompilerDatastore;

class CompilerInspector
{
    protected ProgramTransactionCompilerDatastore $compilers;

    public function __construct(ProgramTransactionCompilerDatastore $compilers)
    {
        $this->compilers = $compilers;
    }

    public function getCompilers(int $programId): array
    {
        return $this->compilers->getProgramTransactionCompilers($programId);
    }
}
use Siren\Programs\Core\Facades\ProgramTransactionCompilers;

$compilers = ProgramTransactionCompilers::getProgramTransactionCompilers($programId);

foreach ($compilers as $compiler) {
    echo $compiler->getTransactionCompiler();
}

getProgramTransactionCompilers returns all transaction compiler records for a given program.

Relationships

  • Collaborators (enrollment). Collaborators are enrolled in programs. The collaborators and collaboratorCount extended fields surface this relationship. A collaborator may belong to multiple programs.
  • Engagement Types (configuration). Each program defines which engagement types are valid for attribution. These are stored in a junction table and surfaced via the engagementTypes extended field.
  • Transaction Compilers (configuration). Programs declare which transaction compilers apply when calculating conversion value. Surfaced via the transactionCompilers extended field.
  • Program Groups (organization). Programs can be organized into groups via a junction table. The list endpoint supports filtering by programGroupId.
  • Conversions (downstream). When an engagement attributed to a program results in a tracked outcome, a conversion is created referencing the program.
  • Obligations (downstream). Approved conversions produce obligations governed by the program’s incentive configuration.

REST endpoints

See the individual endpoint pages in the sidebar for full request and response details, or browse the all REST endpoints reference.