URL: /code/files/audiences · Id: `page:/code/files/audiences`

# The audiences/ folder: one file and what it compiles to

> What one audiences/ file holds, what each key compiles to, and the checks that read it.

One `audiences/` file is one [Audience](https://startupbuilder.dev/business/nouns/audience): who is in, who is left out and what fills it. SalesBuilder compiles it, and `show` traces every key.

```mdx title="audiences/lapsed-leads.mdx"
---
where: "lead.status = 'nurture' and lead.touchedAt < '-60d'"
or: "deal.status = 'lost' and deal.lostAt < '-90d' and deal.lostReason in ('price', 'missing-capability')"
exclude: [suppressed, customers]
fill: [enrichment]
---
Leads nobody has touched in 60 days, and Deals lost on price or a missing capability.
```

```text title="show"
$ npx startup-builder show audiences/lapsed-leads.mdx
where    "lead.status = 'nurture' and lead.touchedAt < '-60d'"                     audiences/lapsed-leads.mdx:2
or       "deal.status = 'lost' and deal.lostAt < '-90d' and deal.lostReason in (…  audiences/lapsed-leads.mdx:3
exclude  [suppressed, customers]                                                   audiences/lapsed-leads.mdx:4
fill     [enrichment]                                                              audiences/lapsed-leads.mdx:5
owner    SalesBuilder
```

```text title="leaseline.app"
leaseline.app/
├── plays/
│   ├── cold-email.mdx
│   ├── warm-intros.mdx
│   ├── signup-interviews.mdx
│   ├── lead-reactivation.mdx
│   └── events-and-webinars.mdx
├── audiences/   ← this folder
│   ├── small-property-managers.mdx
│   ├── lapsed-leads.mdx
│   └── renewal-season.mdx
├── sequences/
│   └── cold-email-thread-founder.mdx
├── funnels/
│   └── signup.mdx
├── workflows/
│   └── outbound.mdx
├── agents/
│   ├── sales/prospector.mdx
│   └── marketing/content-lead.mdx
├── systems/
│   └── sequences.mdx
├── domains/
│   └── leaseline.app.mdx
├── offers/
│   ├── pro.mdx
│   └── team.mdx
├── content/
│   └── webinars/60-day-notices.mdx
├── metrics/
│   ├── q4.mdx
│   └── positive-reply-rate.mdx
└── startups.lock
```

## The file
| Key | On the page | Compiles to | Checked by |
| --- | --- | --- | --- |
| `where` | Who is in | the List’s query, read by <Op verb="Collection.query" /> | [S3](/code/checks#s3) |
| `or` | Also in | a second query, joined to the first | [S3](/code/checks#s3) |
| `exclude` | Left out | suppressed Contacts and active Customers, always; the key may add, never drop | [S3](/code/checks#s3) |
| `fill` | Filled by | the capabilities that enrich it, run after the held-back split, so only treated Contacts are enriched (<Op verb="Contact.enrich" />) | — |

## Checks
| Check | It holds | What dev prints |
| --- | --- | --- |
| [S3](/code/checks#s3) | Lists leave out suppressed Contacts and read Consent. | `audiences/lapsed-leads.mdx:4  S3  exclude: drops suppressed. Suppressed Contacts never enter a List: put it back.` |

## Refusals
| Code | Fix, then the call that clears it |
| --- | --- |
| [`buyer-stop`](/code/refusals#check-buyer-stop) | Send nothing more, and suppress the Contact on every channel. Then <Op verb="Contact.suppress" />. |
| [`consent-stop`](/code/refusals#check-consent-stop) | Ask once for a yes to the other Startup. Then <Op verb="Message.schedule" />. |
| [`customer-collision`](/code/refusals#check-customer-collision) | Send it to their CSM instead: the Contact leaves the List. Then <Op verb="Lead.assign" />. |
| [`no-consent`](/code/refusals#check-no-consent) | Record the Contact’s yes, with where they gave it, before the first send. Then <Op verb="Consent.create" />. |
| [`suppressed-contact`](/code/refusals#check-suppressed-contact) | Leave them out: run the List again, which drops every suppressed Contact. Then <Op verb="Collection.query" />. |

## Calls

```text title="audiences/ compiled · Ask"
Build the small-property-managers List and enrich one Contact on it, as a dry run.
```

```ts title="audiences/ compiled · SDK"
import { $ } from 'startup-builder'

await $.Audience.create({ id: 'audience_1', type: ['noun_1'] }, { mode: 'try' })   // audiences/small-property-managers.mdx
return await $.Contact.enrich({ contact: 'contact_1' }, { mode: 'try' })   // after the held-back split, only treated Contacts
```

```json title="audiences/ compiled · Response · sample"
{
  "contact": {
    "$id": "https://api.sb/leaseline.app/contacts/contact_1",
    "$type": "Contact",
    "email": "dana@leaseline.app",
    "phone": "Example phone"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Contact.enrich",
    "status": "done"
  }
}
```

| Call | What it does |
| --- | --- |
| <a id="contact-enrich"></a><Op verb="Contact.enrich" /> | Enrich fills a Contact’s missing fields from outside sources and marks each value with where it came from. Emits [`Contact.enriched`](/code/events#contact-enriched). |
| <a id="contact-merge"></a><Op verb="Contact.merge" /> | Merge joins a duplicate Contact into another, keeping every link, Message and Event on the one that remains. Emits [`Contact.merged`](/code/events#contact-merged). |
| <a id="visitor-identify"></a><Op verb="Visitor.identify" /> | Identify joins a Visitor to the Contact it turns out to be, so earlier Visits count toward that person. Emits [`Visitor.identified`](/code/events#visitor-identified). |
| <a id="organization-merge"></a><Op verb="Organization.merge" /> | Merge joins a duplicate Organization into another, keeping every Contact, Deal and Event on the one that remains. Emits [`Organization.merged`](/code/events#organization-merged). |
| <a id="prospect-engage"></a><Op verb="Prospect.engage" /> | Engage records a Prospect’s first reply or raised hand and makes it a Lead that keeps its Acquisition. Emits [`Prospect.engaged`](/code/events#prospect-engaged). |
| <a id="lead-qualify"></a><Op verb="Lead.qualify" /> | Qualify confirms a Lead matches an Offer’s ICP and opens a Deal for it. Emits [`Lead.qualified`](/code/events#lead-qualified). |
| <a id="lead-assign"></a><Op verb="Lead.assign" /> | Assign gives a Lead one owner Worker, by round robin, territory or ICP fit, as the Startup’s routing Policy says. Emits [`Lead.assigned`](/code/events#lead-assigned). |
| <a id="contact-suppress"></a><Op verb="Contact.suppress" /> | Suppress records a Suppression for a Contact’s address, which every Startup honors forever. Emits [`Contact.suppressed`](/code/events#contact-suppressed). |

| Not live yet | Use today |
| --- | --- |
| `Organization.enrich` | [Gaps #2](/code/reference#gap-data-verbs). Today: <Op verb="Contact.enrich" /> and <Op verb="Lead.create" />, one Contact at a time. |
| `Contact.import` | [Gaps #2](/code/reference#gap-data-verbs). Today: <Op verb="Contact.enrich" /> and <Op verb="Lead.create" />, one Contact at a time. |
| `Prospect.find` | [Gaps #2](/code/reference#gap-data-verbs). Today: <Op verb="Contact.enrich" /> and <Op verb="Lead.create" />, one Contact at a time. |