TEASEDocs
ProductsClubHow-to

Create a source-link rule

Author a durable rule mapping an OnlyFans link identity to a source, so future fans auto-attribute without manual confirmation.

A source_link row is a standing rule: bind one OnlyFans link identity to one real domain-source you've registered. Confirming a scanned campaign (see Confirm the source for a scanned campaign) writes one of these for you automatically — this page is for authoring one directly, typically a broader pattern that should catch links you haven't scanned yet.

Create a rule

curl -X POST "https://app.tease.link/api/admin/source-links" \
  -H "Authorization: Bearer $TEASE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "match_type": "name_prefix",
    "match_value": "insta_",
    "domain_source": "ig-main.link",
    "channel": "instagram"
  }'

match_type is one of four, checked in this order of what they mean (not priority — see below):

match_typeMatches when
provider_idThe link's vendor id equals match_value exactly.
exact_nameThe link's name equals match_value exactly.
name_prefixThe link's name starts with match_value.
regexmatch_value matches anywhere in the name (re.search, case-insensitive).

domain_source must be a real registered domain — the endpoint 404s on an unknown host and 400s if you try to target __organic__ or __pending__; those sentinels are reserved for "no link at all" and "not mapped yet," never an owner-chosen destination.

A regex is validated at write time, not just at match time

A pathological pattern (nested quantifiers like (a+)+, or an alternation under a quantifier like (a|aa)+) can hang the attribution worker with no timeout available in stdlib re. The create endpoint rejects those shapes outright, caps the pattern at 200 characters, and limits it to 12 groups / 24 quantifiers. If your pattern is refused, fall back to exact_name or name_prefix — real OF link names rarely need more.

Evaluation order

When a link matches more than one active rule, rows are scanned in ascending priority, then by row id, and the first match wins. priority defaults to 100 for every rule created through this endpoint — the API doesn't currently expose a way to set it — so among your own manually-created rules, ties break on creation order (the older rule wins). The one place a lower priority is set automatically is the confirm-campaign flow, which writes its provider_id rule at priority: 10 specifically so an explicit owner pick beats a broad pattern you wrote earlier.

List, update, and delete

curl "https://app.tease.link/api/admin/source-links" \
  -H "Authorization: Bearer $TEASE_API_KEY"

Newest first. A team member scoped to specific sources only sees rules targeting their domains.

curl -X PATCH "https://app.tease.link/api/admin/source-links/42" \
  -H "Authorization: Bearer $TEASE_API_KEY" -H "Content-Type: application/json" \
  -d '{"active": false}'

Every field is optional; domain_source/channel/active/notes can change. match_type and match_value cannot — delete and recreate the rule instead. Setting notes to an explicit empty string clears it.

curl -X DELETE "https://app.tease.link/api/admin/source-links/42" \
  -H "Authorization: Bearer $TEASE_API_KEY"

204 on success. You can't touch a rule targeting a domain outside your team scope — it 404s the same way an unknown id would.

GET /api/admin/unassigned-links lists links the poller has seen traffic on but that no active rule matches yet — a triage queue, newest-active first. It's read-only from this API; a rule (or a campaign confirmation) is what clears an entry off it.

What's next

On this page