---
title: "Create stoplist entries"
method: POST
path: "/api/stoplist-entries"
tags: ["stoplist_entries"]
---

# Create stoplist entries

`POST /api/stoplist-entries`

## Request

- Base URL: `https://beta.getsales.io/playtables/v1`
- URL: `https://beta.getsales.io/playtables/v1/api/stoplist-entries`
- Auth: HTTP bearer and API key in header `Team-SID`

Block identifiers from all outreach, enforced at import, workflow entry, dispatch and sends. One identifier_type and 1..500 values per call. Values are normalized, in-batch duplicates collapse, listed values return their live row (already_exists true). Atomic: one bad value fails the whole call (field_errors per index) and nothing is written. New rows flip matching people to stoplisted (async). source csv_import marks values from a file.

Contract:
- MCP tool `create_stoplist_entry`, registry package `mcp.playtables/stoplist_entries`, mount `playtables.stoplist`.
- Operation `create`, response envelope `create`.
- Flags: none.

## Request body

- CreateStoplistEntryRequest: Request body of `create_stoplist_entry`.
  - `identifier_type` 'ln_member_id' | 'email' | 'domain' | 'ln_nickname' | 'company_ln_nickname', required: The kind of ALL values in the call: ln_member_id (digits, or a profile, Sales Navigator or Recruiter URN, bare or in a URL), email, domain (the company and everyone by email domain), ln_nickname (profile slug/URL), company_ln_nickname (page slug/URL).
  - `values` string[], required: 1..500 identifiers, normalized server-side: ln_member_id to the base-10 id (a known URN decodes, a slug is a per-index 422); email trimmed and lowercased; domain to the bare host (punycode); a nickname kind to its lowercased slug (a URL reduces to it).
  - `source` 'csv_import': Say the batch was read out of a file: csv_import. Omit it for a typed or pasted list (the server stamps manual, or api for an API-token actor). The only value a caller may name; it changes how rows read back in search and counts, never how values match.

## Response `200`

`create` success envelope.

- CreateStoplistEntryResponse
  - `success` true, required
  - `operation` 'create', required
  - `items` object[], required: One element per distinct normalized value, in input order (in-batch duplicates collapse).
    - `item` object, required
      - `sid` string, required: Stoplist entry sid (sl_sl_…).
      - `team_sid` string, required: Owning team (ts_tm_…, external - gs.service.id).
      - `identifier_type` 'ln_member_id' | 'email' | 'domain' | 'ln_nickname' | 'company_ln_nickname', required: What kind of identifier this row blocks: ln_member_id | email | domain | ln_nickname | company_ln_nickname.
      - `value` string, required: NORMALIZED identifier: the member id as base-10 digits (698599037), lowercase email, bare hostname (acme.com), or a lowercased vanity slug (janecooper, acme-corp). Raw input is not stored, and a URL or a URN never is.
      - `source` 'manual' | 'csv_import' | 'api' | 'unsubscribe' | 'complaint', required: Write path: manual | csv_import | api | unsubscribe. Stamped by the server; csv_import is the one value a user actor may name on create.
      - `data_source_sid` string, nullable, required: Provenance of a row the retired csv_stoplist data source promoted before 2026-09-20 (ds_sc_…); null on every row written since, the csv_import ones included.
      - `data_source_item_sid` string, nullable, required: Provenance of the staged row that produced such an entry (ds_it_…); null on every row written since.
      - `created_by` object, required: Actor that created the entry (AccessIdentityValue).
        - `actor_type` 'user' | 'support' | 'api_key' | 'system' | 'agent', required
        - `actor_sid` string, nullable, required
        - `team_sid` string, required
        - `actor_name` string, nullable: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job.
        - `oauth_client_sid` string, nullable: The acting OAuth client (id_oc_*); null off the OAuth path.
        - `reason` string, nullable: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise.
        - `permissions` object, required: Internal audit context: the grant set the actor held at write time. Not a contract.
        - `cluster_id` integer, nullable: Internal audit context: the cluster that served the write.
        - `trace_id` string, nullable: Internal audit context: the trace id of the request that wrote the row.
      - `deleted_by` object, nullable, required: Actor that un-stoplisted the entry; null while live.
        - `actor_type` 'user' | 'support' | 'api_key' | 'system' | 'agent', required
        - `actor_sid` string, nullable, required
        - `team_sid` string, required
        - `actor_name` string, nullable: The OAuth client that acted ("Claude", "n8n"); null for a user, an API key or a system job.
        - `oauth_client_sid` string, nullable: The acting OAuth client (id_oc_*); null off the OAuth path.
        - `reason` string, nullable: Why a system actor wrote the row (snapshot_capture_job, ...); null otherwise.
        - `permissions` object, required: Internal audit context: the grant set the actor held at write time. Not a contract.
        - `cluster_id` integer, nullable: Internal audit context: the cluster that served the write.
        - `trace_id` string, nullable: Internal audit context: the trace id of the request that wrote the row.
      - `created_at` string, required: ISO 8601 UTC.
      - `updated_at` string, required: ISO 8601 UTC; always equals created_at - rows have no update path.
      - `deleted_at` string, nullable, required: ISO 8601 UTC; null = live entry (soft delete).
    - `already_exists` boolean, required: true = this normalized value was already live on the list; the existing row is returned as-is.
  - `created_count` integer, required: New rows inserted by this call.
  - `already_listed_count` integer, required: Values that were already live on the list (existing rows returned, nothing re-inserted).
  - `meta` object, required
    - `trace_id` string, required: UUID v7; same 128-bit value as the X-Trace-Id header.
    - `span_id` string, required: 16 hex chars, root span of this request.
    - `timestamp` string, required: ISO 8601 UTC (Y-m-dTH:i:sZ), response time.
    - `duration_ms` integer, required: Server-side wall clock.
    - `team_sid` string, nullable: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends.
    - `actor_type` string, nullable: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends.

## Other responses

- `4XX`: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented.
- `5XX`: MCP error envelope with `error.code` internal_error or service_unavailable.

---

[API](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables.md) - [All operations](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/llms.txt) - [OpenAPI document](https://skmtc.dev/getsales/apis/getsales-public-contract-gs-service-playtables/revisions/aa394506515d?raw)
