---
title: "Correct what the extractor read, or which contact the row points at"
method: PATCH
path: "/api/news/submissions/{id}/contacts/{newsContactId}"
tags: ["News"]
---

# Correct what the extractor read, or which contact the row points at

`PATCH /api/news/submissions/{id}/contacts/{newsContactId}`

## Request

- Base URL: `https://api.sponsorunited.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.sponsorunited.com/api/news/submissions/{id}/contacts/{newsContactId}`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/sponsorunited/apis/sponsorunited-api/docs/api/news/submissions/:id/contacts/:newsContactId/patch.ts> (a function with typed inputs; its response is checked against the schema)

Only the fields present in the body are written; an explicit null clears a nullable one. The extractor's confidence, the resolver's score and shortlist, and every field the add pipeline owns are refused rather than ignored, so a caller is never told a write landed when it did not.

## Path parameters

- `id` integer, required
- `newsContactId` integer, required

## Request body

- UpdateNewsContactRequest: At least one settable field is required.
  - `name` string: The person's name. Decides which extracted quote attaches when the contact is added, so correcting a mis-read name also fixes quote attachment.
  - `title` string, nullable: Send null to clear it; omit to leave it unchanged.
  - `company` string, nullable
  - `role_context` string, nullable: Free text explaining how the person appears in the article.
  - `submitted_linkedin_url` string, nullable: A LinkedIn member profile URL. Distinct from the profile the sourcing agent finds.
  - `matched_contact_id` integer, nullable: Point the row at a different platform contact, or send null to clear the match. The person profile and entity columns are derived from it, never sent.
  - `match_status` 'dismissed' | 'needs_review': needs_review brings back a row dismissed by mistake.

## Response `200`

The contact as it now stands.

- object
  - `data` NewsContactResource: One person extracted from an article, or supplied with it.
    - `id` integer: One extracted person, in the shape the article payload has always used. The submission payload renders every row through this and the single-contact routes render one, so a reviewer editing a contact reads back exactly the shape the article page will show them (OP-1514, OP-1515).
    - `name` string
    - `title` string, nullable
    - `company` string, nullable
    - `role_context` string, nullable
    - `confidence` number, float
    - `source` 'extracted' | 'submitted': Whether the row came from the article's own extraction or arrived with the submission.
    - `submitted_linkedin_url` string, nullable: A LinkedIn profile supplied with the submission. Distinct from the `add.linkedin_url` the sourcing agent finds.
    - `match` NewsExtractionMatch: Entity-mapping resolver verdict for one extracted person (OP-966/967/968).
      - `status` 'pending' | 'auto_match' | 'needs_review' | 'no_match'
      - `confidence` number, float, nullable
      - `resolved_at` string, date-time, nullable
      - `person_profile_id` integer, nullable
      - `contact_id` integer, nullable
      - `contactable_type` 'agency' | 'brand' | 'property', nullable: Morph alias of the resolved entity; pairs with contactable_id to open the Administration Contacts context.
      - `contactable_id` integer, nullable
      - `entity_name` string, nullable: Name of the resolved agency / brand / property.
      - `candidates` object[]: Resolver top-K candidates; empty when the row was never resolved.
    - `current` NewsExtractionMatchedContact, nullable: Present-day platform values of the matched contact, for side-by-side comparison against the extracted ones. Null when the extraction resolved to no contact.
      - `id` integer
      - `name` string, nullable
      - `email` string, nullable
      - `position` string, nullable
      - `linkedin` string, nullable
    - `add` NewsExtractionAdd: Outcome of adding this extracted person to the platform. Contacts only — a quote becomes a note on a contact, never a contact of its own. `not_added` is the only selectable state; `needs_review` means the sourcing agent found profiles but could not choose between them.
      - `status` 'not_added' | 'processing' | 'needs_review' | 'created' | 'updated' | 'failed'
      - `added_at` string, date-time, nullable: When the reviewer clicked Add contacts selected.
      - `contact_id` integer, nullable: The platform contact this row produced.
      - `error` string, nullable: Readable failure reason when status is failed.
      - `linkedin_url` string, nullable: The profile in play for this row: the one it was created from when status is created, or the one last tried when status is processing or failed. With `candidates` still populated, a failed row can offer the same pick again instead of re-running the search.
      - `candidates` object[]: Profiles the agent found but could not choose between. Present when status is needs_review; the reviewer picks one and posts it to the resolve endpoint.
        - `slug` string
        - `linkedin_url` string
        - `title` string
        - `snippet` string
        - `position` integer

## Other responses

- `403`: Forbidden — missing edit news permission
- `404`: Article or extracted contact not found
- `422`: Nothing settable was sent, a value was rejected, or a field the API does not accept was present

---

[API](https://skmtc.dev/sponsorunited/apis/sponsorunited-api.md) - [All operations](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/llms.txt) - [OpenAPI document](https://skmtc.dev/sponsorunited/apis/sponsorunited-api/revisions/cbf1ca5bff8f?raw)
