Visibility rules
A visibility rule is a server-evaluated condition that controls whether a given deal is shown. Rules attach to a deal and combine partner-level dimensions (partner and partner type) with per-member dimensions (the user's type(s) and region(s)). Where each dimension applies depends on the endpoint: the partner-scoped catalogue listing (GET /v1/deals) evaluates only the partner-level dimensions — it has no end user in scope — while the per-member dimensions are enforced where a member is in scope, namely the hosted end-user listing and GET /v1/deals/{id}/instructions.
:::info Portal-API endpoint
Visibility-rule management lives under /v1/portal/*. The endpoint accepts either a Firebase ID token (used by the partner-portal UI) or your Partner API JWT — so partners can manage rules programmatically alongside the dashboard.
:::
Request shape
Every create call uses the same body:
{
"deal_id": "018e4b2a-0000-7def-abcd-000000000010",
"rule_type": "include_region",
"rule_value": ["Europe", "North America"],
"priority": 0
}
| Field | Type | Required | Notes |
|---|---|---|---|
deal_id | uuid | Yes | The deal the rule applies to |
rule_type | enum | Yes | One of the include/exclude variants below |
rule_value | array of string | Yes | Operand values — semantics depend on rule_type |
priority | integer | No | Evaluation order (default 0) |
Common patterns
Region-locked deal
Only show this deal to users in Europe or North America:
curl -X POST https://perks.founderpass.com/v1/portal/deals/{deal_id}/visibility-rules \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"deal_id": "{deal_id}",
"rule_type": "include_region",
"rule_value": ["Europe", "North America"],
"priority": 0
}'
Hide a deal from a specific user type
Block the deal for users tagged "Idea stage":
{
"deal_id": "{deal_id}",
"rule_type": "exclude_user_type",
"rule_value": ["Idea stage"],
"priority": 0
}
Allow only certain partner types
Useful when configuring a global deal that should only reach accelerators and incubators:
{
"deal_id": "{deal_id}",
"rule_type": "include_partner_type",
"rule_value": ["Accelerator", "Incubator"],
"priority": 0
}
Updating and deleting rules
# Update — body is partial; only send the fields you want to change
curl -X PATCH {API_BASE}/v1/portal/visibility-rules/{rule_id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "rule_value": ["Europe"], "priority": 1 }'
# Delete
curl -X DELETE {API_BASE}/v1/portal/visibility-rules/{rule_id} \
-H "Authorization: Bearer $TOKEN"
Rule types
All rule types follow the same include_* / exclude_* pattern. Include means "only these"; exclude means "everyone except these".
rule_type | rule_value contains | Behaviour |
|---|---|---|
include_partner | Partner UUIDs | Show only to listed partners |
exclude_partner | Partner UUIDs | Hide from listed partners |
include_partner_type | PartnerType values | Show only to these partner types |
exclude_partner_type | PartnerType values | Hide from these partner types |
include_region | AudienceRegion values | Show only in listed regions |
exclude_region | AudienceRegion values | Hide from listed regions |
include_user_type | UserType values | Show only to these user types |
exclude_user_type | UserType values | Hide from these user types |
:::warning Regions are named, not ISO codes
AudienceRegion values are named regions (Europe, North America, Asia, ...) — not ISO 3166-1 country codes. See Enumerations for the full list.
:::
How rules combine
Multiple rules on the same deal AND together — the user must satisfy every rule to see the deal. To express OR within one dimension (e.g. "Europe or North America"), put both values in a single rule's rule_value array.
Toggling a global deal on or off
If you just want to hide a global FounderPass deal from your portal without writing a rule, use the per-deal visibility toggle:
curl -X PATCH https://perks.founderpass.com/v1/portal/deals/{deal_id}/visibility \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "visible": false }'
See the API Reference for the full response schemas.
api_excluded vs other controls
Three different mechanisms can keep a deal out of a listing. They operate at different scopes — don't confuse them:
| Control | Who sets it | Scope | Effect |
|---|---|---|---|
| Visibility rules | Partner (this guide) | Per-deal, per-segment | Gate a deal by partner, partner type, region, or user type |
Visibility toggle (partner_deal_visibility) | Partner | Per-deal, per-partner | Hide a single global deal from your portal — affects both the hosted app and the Partner API |
api_excluded | FounderPass super_admin | Per-deal, channel-scoped | Removes the deal from the Partner API only (GET /v1/deals, detail, instructions, attributed tracking), while it stays live in the hosted app |
hidden_globally | FounderPass super_admin | Per-deal, everywhere | Pulls the deal from every channel for every partner |
The key distinction: api_excluded is channel-scoped, not partner-scoped. A deal marked api_excluded never appears on any Partner API path for any partner, yet end users still see and claim it in the hosted storefront. You can't change api_excluded yourself — it's an admin-side flag — but you'll see it reflected as the deal simply being absent from your API responses. The api_excluded boolean is surfaced on the Deal model for reference.