---
title: "Refresh a table from its source now"
method: POST
path: "/tables/{table_id}/source/run/"
tags: ["table-sources"]
---

# Refresh a table from its source now

`POST /tables/{table_id}/source/run/`

## Request

- Base URL: `https://api.getoneprofile.ai` (the document declares no server; this is the origin it was published from)
- URL: `https://api.getoneprofile.ai/tables/{table_id}/source/run/`
- Auth: one of:
  - API key in header `X-API-Key`
  - HTTP bearer

Start an import immediately. Where the provider supports it and the table has synced before, only records changed since the last successful run are fetched; otherwise everything is re-listed.

`full_relist` re-fetches every record without deleting anything. `delete_missing_rows` additionally removes rows whose records the source no longer returns: a separate, destructive ask, refused while the source has a row limit.

Refused while an import is already running: two concurrent imports would race the same rows.

## Path parameters

- `table_id` string, uuid, required

## Request body

- RunTableSourceRequestSchema: What kind of refresh to run. Two independent asks, not one dial. Re-fetching every record is safe and routine; deleting local rows whose records are gone is destructive and deliberate. Both default to off, so a plain refresh stays the cheap incremental one.
  - `delete_missing_rows` boolean: Delete imported rows whose records the source no longer returns. Implies a full re-list, and is refused while the source has a row limit: a capped import cannot tell a deleted record from one it never fetched.
  - `full_relist` boolean: Re-fetch every record instead of only those changed since the last run. Updates rows; never deletes any.

## Response `202`

Successful Response

- TableSourceRunSchema: One import run's progress and outcome.
  - `error` string, nullable, required
  - `error_code` string, nullable: Classified cause of the failure: unauthorized, rate_limited, server_unavailable, network_error, not_found, pagination_error, bad_request. NULL when the run did not fail.
  - `finished_at` string, date-time, nullable, required
  - `id` string, uuid, required
  - `identity_field` string, nullable, required: The field records were matched on during this run. Null for a run from before this was recorded; read the source's current identity_field instead in that case.
  - `is_full_relist` boolean, required: Whether this run asked the provider for everything.
  - `needs_reconnect` boolean: Whether fixing this means reconnecting the integration. Only true for a credentials failure, so the prompt keeps its meaning.
  - `rows_created` integer, required
  - `rows_deleted` integer, required
  - `rows_skipped` integer, required: Records the run read and left out, broken down by the two counts below. Stopping at the row limit is not a skip; see stopped_at_row_limit.
  - `rows_skipped_duplicate` integer, required: Of those, records whose match value an earlier, different record in the same page already had; only the first was added.
  - `rows_skipped_no_identity` integer, required: Of those, records that came back with no value for the field rows are matched on, so there was no row for them to be.
  - `rows_updated` integer, required
  - `source_id` string, uuid, required
  - `started_at` string, date-time, required
  - `status` 'running' | 'cancelling' | 'cancelled' | 'succeeded' | 'failed', required: Where one import run has got to. The terminal states are absorbing: a run never leaves them. There is no PENDING here. Unlike a CSV upload, which sits parsed and uncommitted until the user says go, a source run is only ever created at the moment something decides to run it. CANCELLING is a request, not an outcome. Stopping an import is a database status flip the workflow observes between pages, never a Temporal terminate: a terminate could land mid-page and leave rows half-written with nothing to settle the run, which is exactly the stuck state that blocks every future refresh of the table.
  - `stopped_at_row_limit` integer, nullable, required: The row limit this run stopped at with records still unread in the tool; null when it read everything it was asked for. Raising the source's row_limit brings the rest in.
  - `sweep_deletions` boolean, required: Whether this run was asked to delete rows whose records are gone from the tool. A run that stopped at a row limit (stopped_at_row_limit) deletes nothing, because it has not read the whole tool.
  - `table_id` string, uuid, required
  - `trigger` 'initial' | 'manual' | 'scheduled', required: What asked for a run.

## Other responses

- `401`: Unauthorized
- `403`: Forbidden
- `404`: Table has no source
- `422`: Invalid request made to the API.
- `500`: Internal server error.
- `502`: Bad gateway error.
- `503`: Service unavailable.

---

[API](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile.md) · [All operations](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/llms.txt) · [OpenAPI document](https://skmtc.dev/getoneprofile/apis/api-reference-oneprofile/revisions/4a6bd71e3f02?raw)
