
Manage payout methods, structures, assignments, accruals, and payments via the trackagoat v1 API.
All payout endpoints require a Bearer API key. Responses follow the standard { data, error, meta } envelope. Amounts are in cents (integer). Timestamps are ISO 8601 UTC.
Payout methods are org-scoped. Default methods (Venmo, Cash App, PayPal) cannot be deleted — use PATCH { is_active: false } to disable.
List org's payout methods.
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-methods"
# Include disabled methods
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-methods?include_disabled=1"Query parameters
| Parameter | Type | Description |
|---|---|---|
include_disabled | 1 | true | Include inactive methods (org admins only) |
Response fields: id, org_id, name, icon_url, is_default, is_active, metadata, readme, created_at
Create a custom payout method.
curl -X POST \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"name": "Zelle"}' \
https://www.trackagoat.com/api/v1/payout-methodsBody
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✓ | Display name (max 100 chars) |
icon_path | string | null | Storage path from a prior UI icon upload | |
metadata | object | Agent-writable structured data | |
readme | string | null | Markdown notes |
Returns 201 with the created method row.
Fetch a single method.
Update name, active state, metadata, or readme.
curl -X PATCH \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"is_active": false}' \
https://www.trackagoat.com/api/v1/payout-methods/<uuid>Body: name?, is_active?, icon_path?, metadata?, readme? (at least one required)
Delete a custom method. Returns 409 default_method for seeded default methods.
Payout structures define earning rules for creators. Scoped to a project. Rule edits create new immutable versions.
List structures in the org (optionally filtered to a project).
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-structures?project_id=<uuid>"Query parameters
| Parameter | Type | Description |
|---|---|---|
project_id | uuid | Filter to a project |
is_active | true | false | Filter by active state |
limit | number | Items per page (max 100, default 50) |
cursor | string | Pagination cursor |
Create a payout structure (creates version 1 atomically).
# Recurring $50/month
curl -X POST \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{
"project_id": "<uuid>",
"name": "Monthly base",
"period": "monthly",
"amount_cents": 5000,
"currency": "USD",
"criteria_type": "recurring",
"criteria_params": {},
"proration_mode": "skip"
}' \
https://www.trackagoat.com/api/v1/payout-structures
# Goals-based monthly with partial completion
curl -X POST \
-H "Authorization: Bearer tga_<key>" \
Body
| Field | Type | Required | Description |
|---|---|---|---|
project_id | uuid | ✓ | Target project |
name | string | ✓ | Structure name |
period | daily | weekly | monthly | null | ✓ | Payout frequency. Pass null for view_threshold structures. |
criteria_params shapes
// recurring — no params
criteria_params: {}
// goals — pay if creator met their goals
criteria_params: {
mode: "all" | "any" | "n_of_m",
n?: number, // required when mode = "n_of_m"
// Partial completion (only valid when mode = "all")
partial_allowed?: boolean, // default false — enable fractional payouts on missed goals
partial_multiplier?: number, // default 1.0 — scales the partial amount (can exceed 1.0)
min_completion_pct?: number, // default 0 — 0–100; below this avg completion%, no payout fires
}
Partial completion formula (goals, mode = "all"):
When partial_allowed is true and the creator does not fully meet all goals:
min(actual / target, 1.0).completion_pct.completion_pct < min_completion_pct / 100 → no accrual.payout = amount × completion_pct × partial_multiplier.When all goals are fully met, the full amount is paid regardless of partial_allowed.
Returns 201 with { structure_id, version_id }.
Fetch structure detail including current_version, full versions[] history, and assignment_count.
Update a structure. Use kind to distinguish cosmetic edits from rule changes.
# Cosmetic — update name and metadata without creating a new version
curl -X PATCH \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"kind": "cosmetic", "name": "Monthly base v2", "metadata": {"owner": "growth-team"}}' \
https://www.trackagoat.com/api/v1/payout-structures/<uuid>
# Rule edit — creates a new immutable version; existing accruals keep their version
curl -X PATCH \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{
"kind": "rule",
"period": "monthly",
Rule PATCH returns { version_id, version_number }. Cosmetic PATCH returns the updated structure row.
Archive (default) or hard-delete a structure.
# Archive — stops new accruals, preserves historical ones
curl -X DELETE -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-structures/<uuid>"
# Hard delete — blocked with 409 has_accruals if accruals exist
curl -X DELETE -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-structures/<uuid>?mode=hard"Assign or unassign creators to a payout structure.
List currently assigned creators.
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-structures/<uuid>/assignments"| Parameter | Type | Description |
|---|---|---|
include_inactive | 1 | true | Include historically unassigned creators |
limit | number | Default 50, max 100 |
cursor | string | Pagination cursor |
Bulk-assign creators. Returns counts of newly assigned, already-assigned, and not-in-project IDs.
curl -X POST \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"creator_ids": ["<uuid1>", "<uuid2>"]}' \
https://www.trackagoat.com/api/v1/payout-structures/<uuid>/assignmentsReturns { assigned, already_assigned, not_in_project, results }.
Bulk-unassign creators. Existing earned accruals remain payable.
curl -X DELETE \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"creator_ids": ["<uuid1>"]}' \
https://www.trackagoat.com/api/v1/payout-structures/<uuid>/assignmentsAccruals are computed by the nightly cron — they cannot be created via the API.
List accruals with optional filters.
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-accruals?project_id=<uuid>&status=earned"Query parameters
| Parameter | Type | Description |
|---|---|---|
project_id | uuid | Filter to a project |
creator_id | uuid | Filter to a creator |
structure_id | uuid | Filter to a structure |
status | earned | paid | rejected | voided | Filter by status |
from | YYYY-MM-DD |
Fetch a single accrual including inputs_snapshot.
Manually reject or void an earned accrual.
curl -X PATCH \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"status": "rejected"}' \
https://www.trackagoat.com/api/v1/payout-accruals/<uuid>Body: { status: "rejected" | "voided" }
Returns 409 cannot_set_status_on_paid_accrual if the accrual is already paid — void the parent payment first.
List payments with optional filters.
curl -H "Authorization: Bearer tga_<key>" \
"https://www.trackagoat.com/api/v1/payout-payments?project_id=<uuid>&status=paid"Query parameters
| Parameter | Type | Description |
|---|---|---|
project_id | uuid | Filter to a project |
creator_id | uuid | Filter to a creator |
status | paid | rejected | voided | Filter by status |
from | YYYY-MM-DD | Paid at or after this date |
to | YYYY-MM-DD | Paid at or before this date |
Response rows include payout_payment_lines[] (linked accruals) and payout_adjustments[] (over/underpayment lines).
Idempotency key required
Always send an Idempotency-Key header (a UUID) when recording payments. If the request times out, retry with the same key — the server returns the original payment without double-counting.
Record a payment. Set Idempotency-Key header for safe retries.
# Settle all outstanding accruals for a creator
curl -X POST \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"project_id": "<uuid>",
"creator_id": "<uuid>",
"method_id": "<uuid>",
"total_amount_cents": 15000,
"currency": "USD",
"auto_apply_outstanding": true,
"note": "April batch payment"
}' \
https://www.trackagoat.com/api/v1/payout-payments
# Ad-hoc payment with no linked accruals
curl -X POST
Body
| Field | Type | Required | Description |
|---|---|---|---|
project_id | uuid | ✓ | Target project |
creator_id | uuid | null | Creator receiving payment (null for true ad-hoc) | |
method_id | uuid | null | Payout method used | |
total_amount_cents | number | ✓ | Total paid in cents (≥ 0) |
currency |
Returns 201 with the payment row.
Fetch a payment including lines and adjustments.
Void a payment or update metadata/readme.
# Void — reverts linked accruals to "earned"
curl -X PATCH \
-H "Authorization: Bearer tga_<key>" \
-H "Content-Type: application/json" \
-d '{"status": "voided"}' \
https://www.trackagoat.com/api/v1/payout-payments/<uuid>Body: { status?: "voided", metadata?: object, readme?: string | null } (at least one field required)
| Code | HTTP | Description |
|---|---|---|
invalid_api_key | 401 | Missing, expired, or invalid Bearer token |
rate_limit_exceeded | 429 | Daily API quota or per-minute rate limit hit |
limit_reached | 402 | Org plan limit for methods or structures |
invalid_body | 400 | Zod validation failed — see meta.errors |
invalid_query | 400 | Bad query parameter |
amount_centsnumber | null |
| ✓ |
Amount in cents. Pass null for view_threshold structures (each threshold defines its own amount). |
currency | USD | ✓ | Currently only USD |
criteria_type | recurring | goals | cpm | view_threshold | ✓ | Earning rule type |
criteria_params | object | ✓ | Rule-specific params (see below) |
proration_mode | skip | prorate | full | ✓ | Mid-period assignment behavior. view_threshold structures always use skip. |
backfill_on_assignment | boolean | view_threshold only. If true, immediately fires any milestones already crossed by the creator's existing videos on assignment. |
metadata | object | Agent-writable data |
readme | string | null | Markdown notes |
| Period start on or after this date |
to | YYYY-MM-DD | Period end on or before this date |
limit | number | Default 50, max 100 |
cursor | string | Pagination cursor (period_end_at ISO) |
limit | number | Default 50, max 100 |
cursor | string | Pagination cursor (paid_at ISO) |
| string |
ISO 4217, default USD |
tracking_url | string | null | External receipt link |
note | string | null | Free-form note |
paid_at | ISO 8601 | Defaults to now |
accrual_ids | uuid[] | Explicit accruals to settle (takes precedence over auto_apply_outstanding) |
auto_apply_outstanding | boolean | If true and creator_id set, settles all earned accruals for that creator |
adjustment_reason | string | null | Required when total differs from accrual sum |
metadata | object | Agent-writable data |
readme | string | null | Markdown notes |
default_method| 409 |
| Cannot delete a seeded default method |
conflict_name | 409 | Method name already exists in org |
structure_archived | 409 | Cannot assign creators to an archived structure |
has_accruals | 409 | Cannot hard-delete a structure with existing accruals |
cannot_set_paid_directly | 400 | Use POST /payout-payments instead |
cannot_set_status_on_paid_accrual | 409 | Void the parent payment first |
currency_mismatch | 400 | Payment currency doesn't match accrual currency |
accrual_not_settleable | 409 | Accrual is wrong project, status, or currency |
adjustment_reason_required | 400 | Total differs from accrual sum — provide adjustment_reason |
already_voided | 400 | Payment is already voided |
accrual_in_other_payment | 409 | Accrual has been re-paid — void that payment first |
not_found | 404 | Resource not found or not in org |