Refficks

Refficks API reference

What your own server builds on: report events, and manage partners, programs, links and codes with an API key. Commissions and payouts are read only: no endpoint approves or pays one.

Before your first call

Address
https://go.refficks.com/api/v1, then the path below.
Key

Every request sends Authorization: Bearer and a secret key, made on the API keys screen in Refficks.

An organization API key (rk_live_…). Only its hash is stored; the plaintext is shown once at creation.

The whole file
openapi.json, OpenAPI 3.1, for Postman, Insomnia or a client generator.

A sale paid through Stripe needs no call at all: the guides show how a checkout carries the partner.

Your key

Whose key this is, and what it may do.

get/server/me

Whose key this is

The organization the key belongs to, and the key's name, purpose (zapier, make, n8n, or null for a key made on the API keys screen) and abilities, each with a label in words. An automation platform shows this as the connection's name. Nothing in it is part of the key, and any secret key may call it (identify).

Answers

  • 200

    object: key_owner, organization {id, name, currency}, key {id, name, purpose, purpose_label, abilities[{ability, label}]}, dashboard_url.

  • 401

    No key, or a key that is revoked or expired.

  • 403

    A publishable key.

Events

What happened in your business: a sale, a signup, a refund. Refficks credits the partner who sent it.

post/events

Ingest a normalized event

The server-side ingest endpoint. Authenticated with an API key, not a session.

Idempotent: the Idempotency-Key header is required. Replaying the same key with the same payload returns the original event and "status": "duplicate". Reusing it with a different payload is a 409.

Processing is asynchronous: the response acknowledges receipt, it does not report attribution or commission outcomes.

Parameters

NameInWhat it is
Idempotency-Keyrequiredheaderstring

Body: EventInput

FieldWhat it is
event_typerequiredone of "tracking.visit", "tracking.click", "customer.created", "customer.updated", "lead.created", "trial.started", "subscription.created", "subscription.updated", "subscription.cancelled", "invoice.created", "invoice.paid", "invoice.payment_failed", "order.created", "order.refunded", "payment.refunded", "payment.disputed", "payment.dispute_closed", "credit_note.issued"

What a merchant's own server may report.

The line is what the caller is in a position to know. Your system knows what happened in your business. It is not in a position to report what Refficks decided, so the conversion the attribution engine writes, and the lead, deal-registration and opportunity lifecycle Refficks records when somebody acts on a screen, are refused here with a message naming what to send instead.

This list is generated from EventType::ingestable() and asserted against it by the test suite, so it cannot drift from what the endpoint accepts.

external_idstring
occurred_atrequiredstring (date-time)
customerobject
propertiesobject

Normalized payload. Monetary values are integer minor units with an explicit currency.

Answers

  • 202

    Accepted for processing.

  • 401

    Missing or invalid credential.

    Carries Error

  • 402

    TRACKING_PAUSED: the event's occurred_at (now, when it names none) falls while the organization's tracking was paused for being unpaid, so it was not recorded, and never will be. Refunds, disputes, credit notes and a dispute's end are recorded whenever they happened.

    Carries Error

  • 409

    The idempotency key was reused with a different payload.

    Carries Error

  • 422

    The request failed validation.

    Carries Error

Partners

The people and companies who send you customers.

get/server/partners

List partners

Oldest first, tie-broken on the key. A server walks the whole list, and a newest-first page shifts under a paginating caller every time a partner is added: page two repeats a row from page one and drops another. Ascending by a key that only grows means a page already read stays read.

Parameters

NameInWhat it is
pagequeryinteger
per_pagequeryinteger
statusqueryPartnerStatus
lifecycle_stagequeryPartnerLifecycleStage
emailquerystring (email)

An exact address, case-insensitive.

Answers

  • 200

    A page of partners.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

post/server/partners

Add a partner

Nobody is emailed unless the request says so. No portal invitation is sent by default; pass send_portal_invitation: true for one. A person pressing Add Partner is adding one person and watching; a server is a loop, and a first sync that mails two thousand people (several hundred of whom left years ago) cannot be un-sent.

organization_id is never accepted. The tenant comes from the key, and supplying it is a validation error rather than a silently ignored field.

status is refused. A partner created already archived would have a status nobody set and no audit entry could explain; archiving is its own call.

Body

FieldWhat it is
emailrequiredstring (email)
first_namestring or null
last_namestring or null
company_namestring or null
phonestring or null
countrystring

ISO 3166-1 alpha-2, checked against the list. Case does not matter.

timezonestring or null
websitestring (uri) or null
rolesarray of PartnerRole
tagsarray of string
lifecycle_stageone of "applicant", "approved"

Only the two stages that mean something at the moment of arrival. The later ones (onboarded, growing, dormant, at risk) are conclusions drawn from what a partner did, and a record with no history cannot be one. They are reached through /transition.

send_portal_invitationboolean

Answers

  • 201

    The partner.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 402

    The organization's plan limit for this resource has been reached.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 409

    A partner with that address already exists here.

  • 422

    The request failed validation.

    Carries Error

get/server/partners/lookup

Find one partner by something you already have

Exactly one of email or code. Both, or neither, is a 422: "either, and I will guess" is how a lookup quietly answers the wrong question when the two disagree.

A single object or a 404, never a list of length zero or one. An integration should not have to store Refficks' ids to use Refficks, and should not have to unwrap an array to find that out.

code matches any tracking link of theirs, including a retired one: a code out of a year-old newsletter still identifies whose it was.

Parameters

NameInWhat it is
emailquerystring (email)
codequerystring

Answers

  • 200

    The partner.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    Nothing here matches that.

  • 422

    The request failed validation.

    Carries Error

get/server/partners/{partner}

Read one partner

Parameters

NameInWhat it is
partnerrequiredpathUlid

Answers

  • 200

    The partner.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

patch/server/partners/{partner}

Change a partner's details

A genuine partial update: a field sent as null is cleared, a field not sent is untouched.

Details only. status, lifecycle_stage, roles and currency are refused with a message naming the endpoint that does the job: refused rather than ignored, because a silently dropped field returns a 200 and a partner object, and the caller ships. The bug then surfaces months later against the one partner where it mattered.

The scores are refused too. They are computed, and a score a client can set is a score no recommendation built on it means anything.

Parameters

NameInWhat it is
partnerrequiredpathUlid

Body

FieldWhat it is
first_namestring or null
last_namestring or null
company_namestring or null
phonestring or null
countrystring or null
timezonestring or null
websitestring (uri) or null

Answers

  • 200

    The partner, as it now stands.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 409

    Another partner here already uses that address.

  • 422

    The request failed validation.

    Carries Error

post/server/partners/{partner}/transition

Move a partner between lifecycle stages

Separate from PATCH because a stage change is a decision with consequences (it fires automations, it stamps approved_at, it is what lets somebody into the portal), and an edit to a field is not.

The legal moves are the same ones a person gets. An illegal one is a 409, so a server cannot walk a partner around the funnel a screen would refuse to.

Parameters

NameInWhat it is
partnerrequiredpathUlid

Body

FieldWhat it is
lifecycle_stagerequiredPartnerLifecycleStage
reasonstring or null

Answers

  • 200

    The partner, at their new stage.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 409

    That move is not one this stage allows.

  • 422

    The request failed validation.

    Carries Error

post/server/partners/{partner}/archive

Archive a partner

Archiving, not deleting. A partner is attached to conversions, ledger entries and payouts; removing the row would make last quarter unreconcilable. It also stops their tracking: an archived partner's links stop earning.

Security review F-25: refused with 403 to a key made for an automation platform, and so is restoring.

A POST to a named path rather than a DELETE, because DELETE promises removal and this keeps everything.

Erasure is deliberately absent from this surface. It takes a typed confirmation from somebody who has read the sentence saying it cannot be undone, and a token cannot read a sentence.

Parameters

NameInWhat it is
partnerrequiredpathUlid

Answers

  • 200

    The partner, now archived.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

post/server/partners/{partner}/restore

Put an archived partner back

Their programme memberships are deliberately untouched, here as on the screen: restoring must not reinstate a programme the merchant suspended on purpose before archiving them. Two decisions, and only one of them is being undone.

Parameters

NameInWhat it is
partnerrequiredpathUlid

Answers

  • 200

    The partner, active again.

    Carries ServerPartner

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

Programs

What partners join, and who is in each.

get/server/programs

List programmes

Parameters

NameInWhat it is
pagequeryinteger
per_pagequeryinteger
statusqueryProgramStatus
modulequeryProgramModule

Answers

  • 200

    A page of programmes, oldest first.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

post/server/programs

Create a programme

slug is derived from the name and cannot be chosen here: uniqueness is per organization and there is nothing to check against until the programme exists. It is editable afterwards.

Set default_destination_url: without it every link you later mint has to carry the same URL again, and a link with nowhere to go is refused.

Body

FieldWhat it is
namerequiredstring
descriptionstring or null
moduleProgramModule
statusProgramStatus
default_currencystring
attribution_window_daysinteger

How long after a click a sale still credits the partner, what other platforms call the cookie duration.

auto_approve_partnersboolean
terms_urlstring (uri) or null
default_destination_urlstring (uri) or null

Answers

  • 201

    The programme.

    Carries ServerProgram

  • 401

    Missing or invalid credential.

    Carries Error

  • 402

    The organization's plan limit for this resource has been reached.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 409

    The module this programme needs is not enabled here.

  • 422

    The request failed validation.

    Carries Error

get/server/programs/{program}

Read one programme

Parameters

NameInWhat it is
programrequiredpathUlid

Answers

  • 200

    The programme.

    Carries ServerProgram

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

patch/server/programs/{program}

Change a programme's settings

module is refused: it decides which half of the product a programme belongs to, so changing it would leave everything already recorded under the old one belonging to nothing.

Rates are not here: a key may set no rate, so commission plans are read only.

Parameters

NameInWhat it is
programrequiredpathUlid

Body

FieldWhat it is
namestring
descriptionstring or null
slugstring
statusProgramStatus
default_currencystring
attribution_window_daysinteger

How long after a click a sale still credits the partner, what other platforms call the cookie duration.

auto_approve_partnersboolean
terms_urlstring (uri) or null
default_destination_urlstring (uri) or null

Answers

  • 200

    The programme, as it now stands.

    Carries ServerProgram

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 422

    The request failed validation.

    Carries Error

get/server/programs/{program}/partners

Who is in a programme

Parameters

NameInWhat it is
programrequiredpathUlid
pagequeryinteger
per_pagequeryinteger
statusqueryProgramPartnerStatus
partner_idqueryUlid

Answers

  • 200

    A page of memberships.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

post/server/programs/{program}/partners

Enrol a partner

A tier may be chosen here and not changed afterwards: a tier sets what somebody earns, and a key may set no rate, so a PATCH naming one is refused.

Two things to know before your first script. A partner created while the merchant has exactly one programme is already in it, so enrolling them again is a 409; enrolment is deliberately not idempotent, because a second call that meant to change something and silently did nothing is worse than a conflict you can read. And enrolling somebody mints their first tracking link.

Parameters

NameInWhat it is
programrequiredpathUlid

Body

FieldWhat it is
partner_idrequiredUlid
tier_idUlid or null

Answers

  • 201

    The membership.

    Carries ServerProgramMembership

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 409

    That partner is already in this programme.

  • 422

    The request failed validation.

    Carries Error

patch/server/programs/{program}/partners/{membership}

Suspend a membership, or restore it

status only. tier_id and custom_commission_plan_id are refused with a message naming where they are set. Both decide what somebody earns, and a key may set no rate.

Parameters

NameInWhat it is
programrequiredpathUlid
membershiprequiredpathUlid

Body

FieldWhat it is
statusrequiredProgramPartnerStatus

Answers

  • 200

    The membership, as it now stands.

    Carries ServerProgramMembership

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 422

    The request failed validation.

    Carries Error

Commission plans

What a program pays. Read only: a key may set no rate.

get/server/programs/{program}/commission-plans

What a programme pays (read only)

There is no POST here, and the absence is the decision. A plan sets what everybody earns, and nobody has said a token may set a rate. A write is a 405: the address is real and the method is not.

Ordered by priority, which is the order that decides which plan pays: a merchant reading this list is almost always asking which one applies.

Parameters

NameInWhat it is
programrequiredpathUlid
pagequeryinteger
per_pagequeryinteger

Answers

  • 200

    A page of plans, highest priority first.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 405

    This API does not write what anybody earns.

get/server/programs/{program}/commission-plans/{plan}

Read one commission plan (read only)

Parameters

NameInWhat it is
programrequiredpathUlid
planrequiredpathUlid

Answers

  • 200

    The plan.

    Carries ServerCommissionPlan

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 405

    This API does not write what anybody earns.

Coupon codes

Each partner's discount codes, which credit them at your checkout even without a click.

get/server/coupon-codes

List coupon codes

Parameters

NameInWhat it is
pagequeryinteger
per_pagequeryinteger
partner_idqueryUlid
program_idqueryUlid
statusqueryTrackingStatus
codequerystring

Answers

  • 200

    A page of codes, oldest first.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

post/server/coupon-codes

Make a code for a partner

This does not create a discount in your payment provider. Refficks connects to Stripe as a platform and holds no credential of yours. What this creates is the record that says this code belongs to this partner.

To register a promotion code you already made, send external_promotion_id, with account_id naming which connected account holds it when you have more than one.

Security review F-15: Stripe is asked what the promotion's code is, and a claim whose code is not this code is refused with 422; a promotion another code already claims is refused with 409. A key made for an automation platform cannot claim one at all (403), nor switch a code or link on or off.

code is optional: left out, one is derived from the partner's name, which is what a server looping over two hundred partners wants.

One code per partner per programme, unless the merchant has turned on more than one. A second is a 409.

Body

FieldWhat it is
program_idrequiredUlid
partner_idrequiredUlid
codestring or null
providerstring or null
attribution_priorityinteger
external_promotion_idstring or null
account_idstring or null

The acct_… id of the connected account holding that promotion code.

Answers

  • 201

    The code.

    Carries ServerCouponCode

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 409

    That code is taken, or this partner already has one here.

  • 422

    The request failed validation.

    Carries Error

get/server/coupon-codes/{coupon}

Read one code

Parameters

NameInWhat it is
couponrequiredpathUlid

Answers

  • 200

    The code.

    Carries ServerCouponCode

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

patch/server/coupon-codes/{coupon}

Change a code's limits or where it is placed

code is refused, for the reason a link's is: it is what somebody types at the checkout. Retire this one and make another.

uses_count is refused because it is Refficks' count of redemptions: a merchant who could edit it could hand somebody another fifty uses with no record of having done so.

Sending external_promotion_id: null takes a placement back, which is a different instruction from not sending the field at all.

Parameters

NameInWhat it is
couponrequiredpathUlid

Body

FieldWhat it is
statusTrackingStatus
attribution_priorityinteger
max_usesinteger or null
expires_atstring (date-time) or null
minimum_amountinteger or null

Minor units. Null means the programme's default applies, not "no minimum".

minimum_amount_currencystring or null
first_time_transactionboolean or null
external_promotion_idstring or null
account_idstring or null

Answers

  • 200

    The code, as it now stands.

    Carries ServerCouponCode

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 422

    The request failed validation.

    Carries Error

Commissions

The ledger. Read only: no endpoint approves, rejects or changes a commission.

get/server/commissions

Read the ledger (read only)

occurred_from / occurred_to filter on occurred_at, not created_at: a sale in March recorded in April belongs to March's books.

Paged by id, because a ULID only grows while occurred_at does not: a late-arriving event carries an older date and would insert rows behind a crawler.

No total. A ledger holds several currencies and this API will not sum across them; a figure nobody can spend is worse than none.

Parameters

NameInWhat it is
pagequeryinteger
per_pagequeryinteger
partner_idqueryUlid
program_idqueryUlid
payout_idqueryUlid
statusqueryCommissionEntryStatus
typequeryCommissionEntryType
currencyquerystring
occurred_fromquerystring (date)
occurred_toquerystring (date)

Answers

  • 200

    A page of ledger entries.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 405

    This API does not decide money.

get/server/commissions/{entry}

Read one ledger entry (read only)

Parameters

NameInWhat it is
entryrequiredpathUlid

Answers

  • 200

    The entry.

    Carries ServerCommissionEntry

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 405

    This API does not decide money.

Payouts

What partners were paid. Read only: no endpoint pays anybody.

get/server/payouts

Read payouts (read only)

There is no POST. Refficks moves no money: a payout's status is recorded and the merchant downloads a file for their bank, so there is no transfer for an endpoint to trigger. Read status: paid as the merchant recorded that they sent it.

Parameters

NameInWhat it is
pagequeryinteger
per_pagequeryinteger
partner_idqueryUlid
statusqueryPayoutStatus
currencyquerystring

Answers

  • 200

    A page of payouts.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 405

    This API does not decide money.

get/server/payouts/{payout}

Read one payout (read only)

Parameters

NameInWhat it is
payoutrequiredpathUlid

Answers

  • 200

    The payout.

    Carries ServerPayout

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

  • 405

    This API does not decide money.

get/server/payouts/{payout}/entries

What a payout is made of (read only)

The question a reconciling merchant actually has, answered without making them filter the whole ledger by a payout id and trust that they got all of it.

Parameters

NameInWhat it is
payoutrequiredpathUlid
pagequeryinteger
per_pagequeryinteger

Answers

  • 200

    A page of the entries this payout settled.

  • 401

    Missing or invalid credential.

    Carries Error

  • 403

    Authenticated, but not permitted.

    Carries Error

  • 404

    No such resource, including a resource that belongs to another tenant. Cross-tenant access returns 404 rather than 403, because a 403 confirms the resource exists.

    Carries Error

Subscriptions

Be told when something happens, at an address of yours.

get/server/hooks

List this key's subscriptions

The subscriptions this key made, oldest first, never the merchant's own receivers and never another key's. Needs hooks:manage. Each has url_hint (host and last four characters), never the address.

Answers

  • 200

    hook objects: id, url_hint, events, status, status_label, ended_reason, last_delivered_at, ended_at, created_at.

post/server/hooks

Subscribe to be told

What a REST-hook subscribe sends: {url, event} or {url, events: [...]}, optional description. The address is kept encrypted. Asking again for the same address from the same key answers the same subscription (200, no secret) and starts it again if it had ended; asking from another key while it is live is a 409. Every event needs partners:read; commission and payout events need money:read too (403 naming the ability). At most 200 active per key.

Answers

  • 200

    The subscription this key already had for that address, and secret null.

  • 201

    The subscription, with its signing secret, shown once.

  • 403

    The key lacks hooks:manage, or the read ability the event needs.

  • 409

    Not an event Refficks sends; an address another key subscribed; the per-key limit; or an address Refficks will not send to.

get/server/hooks/events

What may be subscribed to

Every event something in the product raises, with label, needs (the abilities it takes) and subscribable for this key: the dropdown an automation platform shows.

Answers

  • 200

    hook_event objects.

get/server/hooks/samples

What an event looked like recently

Up to three of the merchant's own newest facts for event, newest first, in the shape a delivery has (docs/events.md, "Delivered outward") and with the same id a live delivery of the same fact carries. An empty list when there is nothing yet; nothing is invented. Needs hooks:manage and the read ability the event carries.

Parameters

NameInWhat it is
eventrequiredquerystring

Answers

  • 200

    Deliveries, each with id, event, event_label, occurred_at, partner, program, commission, payout, referral, lead and data.

  • 403

    The key lacks the read ability the event carries.

  • 422

    Not an event Refficks sends.

get/server/hooks/{hook}

One of this key's subscriptions

Parameters

NameInWhat it is
hookrequiredpathstring

Answers

  • 200

    The subscription.

  • 404

    Not a subscription this key made: another key's, a screen-made endpoint, or another account's.

delete/server/hooks/{hook}

Unsubscribe

Ends it and keeps it, with its delivery log; nothing more is sent. A second call is answered the same, because platforms retry.

Parameters

NameInWhat it is
hookrequiredpathstring

Answers

  • 204

    Ended.

  • 404

    Not a subscription this key made.

Objects

What the calls above send and answer with.

CommissionEntryStatus

one of "pending", "approved", "rejected", "reversed", "paid"

CommissionEntryType

one of "earned", "fee", "bonus", "adjustment", "reversal", "payout", "opening", "returned", "owed_again", "recruiter_share"

Error

FieldWhat it is
errorobject

EventInput

FieldWhat it is
event_typerequiredone of "tracking.visit", "tracking.click", "customer.created", "customer.updated", "lead.created", "trial.started", "subscription.created", "subscription.updated", "subscription.cancelled", "invoice.created", "invoice.paid", "invoice.payment_failed", "order.created", "order.refunded", "payment.refunded", "payment.disputed", "payment.dispute_closed", "credit_note.issued"

What a merchant's own server may report.

The line is what the caller is in a position to know. Your system knows what happened in your business. It is not in a position to report what Refficks decided, so the conversion the attribution engine writes, and the lead, deal-registration and opportunity lifecycle Refficks records when somebody acts on a screen, are refused here with a message naming what to send instead.

This list is generated from EventType::ingestable() and asserted against it by the test suite, so it cannot drift from what the endpoint accepts.

external_idstring
occurred_atrequiredstring (date-time)
customerobject
propertiesobject

Normalized payload. Monetary values are integer minor units with an explicit currency.

Money

Minor units plus an ISO-4217 currency. Never a float.

FieldWhat it is
amountinteger
currencystring

PaginatedEnvelope

FieldWhat it is
dataarray of object
metaobject
linksobject

PartnerLifecycleStage

one of "applicant", "approved", "onboarded", "active", "growing", "vip", "dormant", "at_risk", "rejected"

PartnerRole

one of "affiliate", "creator", "ambassador", "referrer", "agency", "reseller", "customer", "consultant"

PartnerStatus

one of "active", "inactive", "suspended", "archived"

PayoutStatus

one of "draft", "pending_approval", "approved", "processing", "paid", "failed", "returned", "cancelled"

ProgramModule

one of "affiliate", "referral", "creator", "ambassador", "agency", "reseller"

ProgramPartnerStatus

one of "pending", "approved", "rejected", "suspended", "left"

ProgramStatus

one of "draft", "active", "paused", "archived"

ServerCommissionEntry

One line of a merchant's ledger. Read only.

An entry carries its own arithmetic: amount, the base_amount it was worked out from, and the rate. A merchant reconciling should be able to see that £14.25 is ten per cent of £142.50 rather than take the figure on trust.

A reversal is a new entry, never an edit: a refund writes a negative row whose parent_entry_id points at the original, and both stay.

FieldWhat it is
objectrequired"commission_entry"
idrequiredUlid
partner_idrequiredUlid
program_idrequiredUlid or null
commission_plan_idrequiredUlid or null
event_idrequiredUlid or null

The event this was worked out from, which ties our ledger to the merchant's own system.

customer_idrequiredUlid or null
parent_entry_idrequiredUlid or null

The entry this one undoes, for a reversal.

typerequiredCommissionEntryType
statusrequiredCommissionEntryStatus
currencyrequiredstring

Governs both amounts. Entries in different currencies are never summed.

amountrequiredinteger

Minor units. Negative on a reversal.

base_amountrequiredinteger or null

What the rate was applied to. Null where the entry is not a percentage of anything.

raterequirednumber or null

A percentage (ten, not 0.1). Null alongside a null base_amount.

descriptionrequiredstring or null
plan_namerequiredstring or null

The plan name recorded at the time. This is a ledger; it says what it said.

payout_idrequiredUlid or null
occurred_atrequiredstring (date-time)

Never null. An entry that did not know when it happened could not be placed in a period, so the column does not allow one.

approved_atrequiredstring (date-time) or null
paid_atrequiredstring (date-time) or null
created_atrequiredstring (date-time) or null

ServerCommissionPlan

What a programme pays. Read only: a key may set no rate, so a POST or PATCH here is a 405.

rules is published verbatim because the rules are the plan: a payload saying type: tiered and declining to say what the tiers were would answer a question nobody asked. The shape inside it belongs to the calculation engine, so changing that shape changes this contract.

FieldWhat it is
objectrequired"commission_plan"
idrequiredUlid
program_idrequiredUlid
namerequiredstring
descriptionrequiredstring or null
typerequiredone of "percentage", "fixed", "tiered", "hybrid"
currencyrequiredstring
recurringrequiredboolean
duration_monthsrequiredinteger or null

Null means for as long as the subscription lasts, a different claim from a number.

auto_approve_after_daysinteger or null

Days after a sale its commission approves itself, or null when a person approves each one. Read-only: setting it is approving money in advance, which only an admin does, in the dashboard.

priorityrequiredinteger

Which plan wins when several could apply. Lower goes first.

statusrequiredstring
rulesrequiredobject
created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

ServerCouponCode

The code a partner's audience types at the checkout. This is the Refficks record, not a discount in anybody's payment provider.

FieldWhat it is
objectrequired"coupon_code"
idrequiredUlid
program_idrequiredUlid
partner_idrequiredUlid
coderequiredstring
providerrequiredstring or null
attribution_priorityrequiredinteger

Which code wins when a basket carries more than one.

statusrequiredTrackingStatus
max_usesrequiredinteger or null
uses_countrequiredinteger

Refficks' count of redemptions. Never writable.

expires_atrequiredstring (date-time) or null
minimum_amountrequiredinteger or null

Minor units. Null means the programme's default applies, not "no minimum". A client reading null as zero is wrong about every code the merchant never overrode.

minimum_amount_currencyrequiredstring or null
first_time_transactionrequiredboolean or null
placementsrequiredarray of ServerCouponPlacement

Per connected account, because a merchant may have several and no single boolean could honestly answer for both. Empty is the ordinary case.

created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

ServerCouponPlacement

This code, as it exists in one connected payment account. Refficks holds no credential, only the non-secret acct_… id.

FieldWhat it is
objectrequired"coupon_placement"
providerrequiredstring or null
integration_idrequiredUlid or null
account_idrequiredstring or null

The account the code is in, as recorded when it was placed, still named after that account is disconnected, when the code is paused rather than gone.

external_promotion_idrequiredstring or null

ServerOwnRate

A partner's own figure on one rule. What the rule covers (its conditions) is the rule's; only the figure is the partner's.

FieldWhat it is
commission_plan_idrequiredUlid
typerequiredone of "percentage", "fixed"
valuerequirednumber

A percentage, or for fixed minor units of currency, as the rule's own rules.action.value is written.

discounted_valuerequirednumber or null

Their figure on a sale with a discount code, when they were given one. Null keeps the rule's.

currencyrequiredstring or null

The rule's currency.

appliesrequiredboolean

Whether this figure is what the rule pays them today.

not_applying_becauserequiredone of "rule_archived", "rule_pays_differently" or null

rule_archived: the rule pays nobody; bringing it back pays this figure again. rule_pays_differently: the rule changed how it pays since the figure was set, so the rule's own figure applies.

reasonrequiredstring or null

The merchant's note on why.

set_atrequiredstring (date-time) or null

ServerPartner

A partner as the management API publishes one.

Distinct from Partner, which is the dashboard's shape and follows its screens. Every property below is always present; absent data is null, never missing. Within v1 properties are added and never removed or repurposed.

The scores (score, potential_score, risk_score) are deliberately absent: they are recomputed on a schedule we change, against a scale nobody outside has agreed to, and automating against one would be automating against an implementation detail.

FieldWhat it is
objectrequired"partner"
idrequiredUlid
statusrequiredPartnerStatus
lifecycle_stagerequiredPartnerLifecycleStage
emailrequiredstring (email)
first_namerequiredstring or null
last_namerequiredstring or null
company_namerequiredstring or null
phonerequiredstring or null
countryrequiredstring or null

ISO 3166-1 alpha-2, stored upper-case.

timezonerequiredstring or null
websiterequiredstring (uri) or null
currencyrequiredstring

ISO 4217. The currency both amounts below are in. On the object rather than implied, because a figure without its currency is a figure somebody will add to another one.

lifetime_revenue_amountrequiredinteger

Minor units (pence, cents) as an integer. Never a decimal string. In lifetime_revenue_currency, the merchant's currency, not currency: sales in other currencies are in lifetime_revenue_by_currency and never added to this. It used to be every currency added together.

lifetime_revenue_currencyrequiredstring

The merchant's currency, which lifetime_revenue_amount is in.

lifetime_revenue_by_currencyrequiredarray of Money

Every currency the partner has sold in, the merchant's first (always present, at 0 if nothing was sold in it), then the largest.

lifetime_commission_amountrequiredinteger

What the partner has earned, in the merchant's currency (lifetime_commission_currency), read from the ledger: every entry that was not rejected, so a reversal nets its sale away. Commission in other currencies is in lifetime_commission_by_currency and never added to this. It used to be a running sum of every currency.

lifetime_commission_currencyrequiredstring

The merchant's currency, which lifetime_commission_amount is in.

lifetime_commission_by_currencyrequiredarray of Money

Every currency the partner has earned in, the merchant's first (always present, at 0 if nothing was earned in it), then the largest.

rolesrequiredarray of PartnerRole

Empty rather than absent for a partner with none.

tagsrequiredarray of string
first_click_atrequiredstring (date-time) or null
first_conversion_atrequiredstring (date-time) or null
last_activity_atrequiredstring (date-time) or null
approved_atrequiredstring (date-time) or null
forgotten_atrequiredstring (date-time) or null

When this record was erased, or null. Published because every other field on a forgotten partner is blanked, so a client left to infer it would be inferring from an absence, and a server syncing records needs to read this person asked to be forgotten rather than this person is called something odd now.

created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

ServerPayout

A payout. Read only, and Refficks moves no money: status: paid means the merchant recorded that they sent it.

payment_details is not here and never will be. Payout details are encrypted at rest and the stored value is never returned to anybody. payment_hint is the mask, and is all this surface says about where money went.

FieldWhat it is
objectrequired"payout"
idrequiredUlid
partner_idrequiredUlid
statusrequiredPayoutStatus
currencyrequiredstring
amountrequiredinteger

Minor units.

entries_countrequiredinteger
payment_methodrequiredstring or null
payment_hintrequiredstring or null

The masked account: enough to recognise it on a statement, useless to anybody who obtains this payload. The real value leaves Refficks through the audited bank export alone.

referencerequiredstring or null
void_reasonrequiredstring or null

Why the merchant called this payout off, in their own words. Readable here because the caller on this surface is the merchant. It is merchant-private: the partner it is about never receives it, on this surface or any other. Earlier versions of the API called it notes.

external_payout_idrequiredstring or null

The merchant's note of a transfer they made elsewhere. Refficks did not put it there.

period_startrequiredstring (date) or null
period_endrequiredstring (date) or null
approved_atrequiredstring (date-time) or null
paid_atrequiredstring (date-time) or null
created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

ServerProgram

A programme as the management API publishes one. Every property is always present; absent data is null.

FieldWhat it is
objectrequired"program"
idrequiredUlid
modulerequiredProgramModule
namerequiredstring
slugrequiredstring

The last part of this programme's public address.

descriptionrequiredstring or null
statusrequiredProgramStatus
default_currencyrequiredstring
attribution_window_daysrequiredinteger

How long a click keeps earning, what other platforms call the cookie duration. Captured at click time, so changing it never re-decides a conversion that already happened.

auto_approve_partnersrequiredboolean
terms_urlrequiredstring (uri) or null
default_destination_urlrequiredstring (uri) or null

Where links under this programme land when the link does not say. Without it, every link you mint must carry its own.

created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

ServerProgramMembership

One partner's place in one programme: where the terms live. custom_commission_plan_id is readable and never writable.

FieldWhat it is
objectrequired"program_membership"
idrequiredUlid
program_idrequiredUlid
partner_idrequiredUlid
statusrequiredProgramPartnerStatus
tierrequiredstring or null
custom_commission_plan_idrequiredUlid or null

A plan of this partner's own that replaced every rule, from before a partner could have a figure per rule. Saving figures per rule on the dashboard retires it. What it pays belongs to the plan.

own_ratesrequiredarray of ServerOwnRate

This partner's own figures on the programme's rules, in force. Read only: a figure is set on the partner's card in the dashboard.

joined_atrequiredstring (date-time) or null
approved_atrequiredstring (date-time) or null
created_atrequiredstring (date-time) or null
updated_atrequiredstring (date-time) or null

TrackingStatus

one of "active", "paused", "archived"

Ulid

string