> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://apidocs.polytomic.com/2024-02-08/guides/2025-09-18-migration-guide/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://apidocs.polytomic.com/_mcp/server. # REST API 2025-09-18 migration guide This guide describes everything that has changed between `2024-02-08` and `2025-09-18`: the new features available, the removed and relocated endpoints, and the request and response shape changes that callers need to adopt. The sections are organized by area. Most clients will only need to update a handful of routes; the [quick checklist](#quick-checklist) at the end summarises the breaking changes. Each section links into the detailed API reference for the affected endpoints. ## What's new `2025-09-18` adds several capabilities that did not exist in `2024-02-08`. ### Connection Proxy API You can now make ad-hoc HTTP requests to a connection's upstream API using the credentials Polytomic already stores. * [`POST /api/connections/{id}/proxy`](/api-reference/connections/execute-proxy) — proxy an HTTP request through a connection. Polytomic attaches the connection's base URL, auth headers, and inherited query parameters; the caller supplies `method`, `path`, optional `query`, `headers`, and `body`. * [`GET /api/connections/{id}/proxy/info`](/api-reference/connections/get-proxy-info) — returns the proxy contract for a connection: the inherited base URL, locked query parameters, locked headers (with sensitive values redacted), allowed HTTP methods, body and header rules, size and rate limits, and 24-hour usage statistics. The proxy enforces per-connection and per-organization rate limits, a 30 second upstream timeout, a 256 KiB request body cap, and a 1 MiB response body cap (responses above that are returned with `truncated: true`). Each call returns a `proxyCallId` you can correlate with audit logs. The feature is enabled by request; contact Polytomic support to enable it. ### Per-execution console logs The console log stream that powers the in-product execution view is now available over the REST API. Each endpoint returns the most recent entries and supports cursor pagination via `limit` and `after`. * [`GET /api/syncs/{sync_id}/executions/{id}/consolelog`](/api-reference/model-sync/executions/get-console-logs) — model sync execution. * [`GET /api/bulk/syncs/{sync_id}/executions/{execution_id}/consolelog`](/api-reference/bulk-sync/executions/get-console-logs) — bulk sync execution, aggregated across schemas. * [`GET /api/bulk/syncs/{sync_id}/executions/{execution_id}/schemas/{schema_id}/consolelog`](/api-reference/bulk-sync/executions/get-schema-console-logs) — bulk sync execution scoped to a single schema. These complement the existing log export endpoints; use console logs while an execution is in flight and the structured logs after it completes. ### Patch schema fields [`PATCH /api/connections/{connection_id}/schemas/{schema_id}/fields/{field_id}`](/api-reference/schemas/patch-field) applies a partial update to a single field. Only the fields you include in the body are changed, so you can rename a label or change a JSONPath without re-sending the rest of the field definition. The existing POST and DELETE endpoints are unchanged. ### Per-schedule resync mode for bulk syncs Each `additional_schedules` entry on a bulk sync now accepts a `resync_mode` (one of `normal`, `refetch`, `resync`, `rebuild`) that controls how the destination is treated when that schedule fires. The previous API supported a single sync-wide schedule and had no way to express "run a daily incremental plus a weekly full rebuild." See [Bulk Sync: list, create, and update](#bulk-sync-list-create-and-update) below for the new payload shape. ### Entity lookup A new endpoint lets you resolve any Polytomic UUID without knowing what kind of resource it belongs to: * [`GET /api/entities/{id}`](/api-reference/entities/get) (user or organization-scoped key) — resolve an ID within the caller's organization. * [`GET /api/organizations/entities/{id}`](/api-reference/entities/get-for-partner) (partner key) — resolve an ID across organizations the partner can access. The response includes the entity `type` (`organization`, `user`, `connection`, `model`, `sync`, `sync_execution`, `bulk_sync`, or `bulk_sync_execution`), a `canonical_path` you can immediately `GET`, and `relationships` for nested resources (e.g. a sync execution returns its parent sync). This is useful when following IDs that appear in logs, webhooks, or audit records. ### Model sync execution logs index [`GET /api/syncs/{sync_id}/executions/{id}/logs`](/api-reference/model-sync/executions/get-logs-index) returns a compact index of the record-log types produced by a model sync execution. The response contains a record count and a per-type retrieval endpoint for each kind of log file that was actually produced (`records`, `inserts`, `updates`, `deletes`, `errors`, `warnings`); types with no records are omitted. This endpoint is the canonical way to discover the signed URLs for execution log segments. It pairs with the [`sync.completed` webhook payload change](#sync-completed-webhook-payload-trimmed) below. ## Authentication and route layout ### Organization and user endpoints split by credential type `2024-02-08` used a single route family for both the caller's own organization and partner cross-organization access, and let the server infer intent from the credential. `2025-09-18` splits these into two distinct route families so that intent is explicit in the URL. | Operation | 2024-02-08 | 2025-09-18 | | ----------------------------------------- | -------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Get current organization | *(not exposed)* | [`GET /api/organization`](/api-reference/organization/get-current) | | Create user in current organization | `POST /api/organizations/{org_id}/users` | [`POST /api/organization/users`](/api-reference/users/create-current-org-user) | | List users in current organization | `GET /api/organizations/{org_id}/users` | [`GET /api/organization/users`](/api-reference/users/list-current-org-users) | | Get user in current organization | `GET /api/organizations/{org_id}/users/{id}` | [`GET /api/organization/users/{id}`](/api-reference/users/get-current-org-user) | | Update user in current organization | `PUT /api/organizations/{org_id}/users/{id}` | [`PUT /api/organization/users/{id}`](/api-reference/users/update-current-org-user) | | Delete user in current organization | `DELETE /api/organizations/{org_id}/users/{id}` | [`DELETE /api/organization/users/{id}`](/api-reference/users/delete-current-org-user) | | List organizations (partner) | `GET /api/organizations` | [`GET /api/organizations`](/api-reference/organization/list) | | Get / update / delete organization | `... /api/organizations/{id}` | [`GET`](/api-reference/organization/get) / [`PUT`](/api-reference/organization/update) / [`DELETE`](/api-reference/organization/delete) `/api/organizations/{id}` | | CRUD users across organizations (partner) | `... /api/organizations/{org_id}/users[/{id}]` | [`Create`](/api-reference/users/create) / [`List`](/api-reference/users/list) / [`Get`](/api-reference/users/get) / [`Update`](/api-reference/users/update) / [`Delete`](/api-reference/users/delete) | | Create API key for a user (partner) | `POST /api/organizations/{org_id}/users/{id}/keys` | [`POST /api/organizations/{org_id}/users/{id}/keys`](/api-reference/users/create-api-key) | **Migration rule.** Decide based on the credential you are using: * A user session or an organization-scoped API key acting **within its own organization** must use `/api/organization/...` (singular). * A partner key acting **across organizations** must use `/api/organizations/...` (plural). The plural routes now reject organization-scoped credentials. If your `2024-02-08` client used the plural routes with a non-partner credential, point it at the new singular routes; the request and response bodies are otherwise unchanged. ### Connection share endpoint moved The connection share endpoints have been harmonized with the rest of the connections surface: | Operation | 2024-02-08 | 2025-09-18 | | --------------------------------- | ---------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------- | | Share a connection (partner) | `POST /api/connections/{parent_connection_id}/share` | [`POST /api/organizations/{org_id}/connections/{connection_id}/shared`](/api-reference/connections/create-shared-connection) | | List shared copies (partner) | `GET /api/connections/{parent_connection_id}/shared` | [`GET /api/organizations/{org_id}/connections/{connection_id}/shared`](/api-reference/connections/list-shared-connections-for-partner) | | List shared copies (caller's org) | `GET /api/connections/{parent_connection_id}/shared` | [`GET /api/connections/{id}/shared`](/api-reference/connections/list-shared-connections) | The trailing path segment is now `shared` (a noun describing the resource collection) rather than `share` (a verb), matching the rest of the API. ## Bulk Sync: list, create, and update The bulk sync [create](/api-reference/bulk-sync/create), [update](/api-reference/bulk-sync/update), [list](/api-reference/bulk-sync/list), and [get](/api-reference/bulk-sync/get) endpoints have been overhauled: * The single `schedule` parameter has been removed. * A required `default_schedule` parameter and an optional `additional_schedules` array have been added. * Each additional schedule can target specific schemas via `selective_mode` and `schemas`, and can override the per-execution resync behavior via `resync_mode`. Every bulk sync now operates in multi-schedule mode by default; the legacy `multi` schedule type is no longer accepted. ### Schedule payload migration **Old `2024-02-08` update payload, using `schedule`:** ```json { "name": "my bulk sync", "schedule": { "frequency": "multi", "multi": { "schedules": [ { "item": "incrementalFields", "schedule": { "frequency": "continuous" } }, { "item": "nonincrementalFields", "schedule": { "frequency": "daily", "hour": "05", "minute": "00" } } ] } } } ``` **New `2025-09-18` update payload, using `default_schedule` and `additional_schedules`:** ```json { "name": "my bulk sync", "default_schedule": { "frequency": "continuous" }, "additional_schedules": [ { "selective_mode": "nonincrementalFields", "frequency": "daily", "hour": "05", "minute": "00" } ] } ``` The `default_schedule` always applies to every schema and field; it cannot carry `selective_mode`, `schemas`, or `resync_mode`. `additional_schedules` entries may scope themselves to specific schemas (`schemas: ["public.users"]`) and may set `resync_mode` (`normal`, `refetch`, `resync`, `rebuild`) to override the default destination behavior when that schedule fires. The response shape of [`GET /api/bulk/syncs`](/api-reference/bulk-sync/list), [`GET /api/bulk/syncs/{id}`](/api-reference/bulk-sync/get), [`POST /api/bulk/syncs`](/api-reference/bulk-sync/create), and [`PUT /api/bulk/syncs/{id}`](/api-reference/bulk-sync/update) mirrors this: each returns a `default_schedule` object and an `additional_schedules` array, both with `created_at` / `updated_at` / `created_by` / `updated_by` metadata. ## Model Sync: list syncs [`GET /api/syncs`](/api-reference/model-sync/list) now returns paginated, lighter-weight results so it can be used for discovery without paying the cost of loading every sync's full configuration: * Results are paginated. The response includes a `pagination.next_page_token` cursor; pass it back as the `page_token` query parameter to retrieve the next page. The page size is capped at 50. * Results are filterable via `active`, `mode`, and `target_connection_id` query parameters. * The list response shape does not include every sync property. Notably: * The target connection is not expanded — only `target_connection_id` and target ID fields are returned. * Field mappings, overrides, and filters are omitted. If you need the full configuration of a sync, follow up with the existing [`GET /api/syncs/{id}`](/api-reference/model-sync/get) endpoint. Use list to discover or filter syncs in an account; use get to retrieve the full configuration of a single one. ## Model Sync executions: explicit cancel The status-update endpoint that was used to cancel a model sync execution has been replaced by an explicit cancel endpoint, mirroring the bulk sync API: | Operation | 2024-02-08 | 2025-09-18 | | ----------------------------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Cancel a model sync execution | `PUT /api/syncs/{sync_id}/executions/{id}` with a status body | [`POST /api/syncs/{sync_id}/executions/{id}/cancel`](/api-reference/model-sync/executions/cancel) | The new endpoint takes no body and returns a confirmation envelope. Attempting to cancel a terminal (completed or failed) execution returns `400`. There is no longer a generic "update execution" endpoint; executions are write-once apart from cancellation. ## Removed endpoints | 2024-02-08 endpoint | Replacement | | ---------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `PUT /api/syncs/{sync_id}/executions/{id}` | [`POST /api/syncs/{sync_id}/executions/{id}/cancel`](/api-reference/model-sync/executions/cancel) | | `GET /api/connections/{id}/modelsync/target` | [`GET /api/connections/{id}/modelsync/target/fields`](/api-reference/model-sync/targets/get-fields) (the target-shape endpoint was redundant with fields) | | `POST /api/connections/{parent_connection_id}/share` | [`POST /api/organizations/{org_id}/connections/{connection_id}/shared`](/api-reference/connections/create-shared-connection) | | `GET /api/connections/{parent_connection_id}/shared` | [`GET /api/connections/{id}/shared`](/api-reference/connections/list-shared-connections) or [the partner-scoped variant](/api-reference/connections/list-shared-connections-for-partner) | ## Quick checklist When upgrading a client from `2024-02-08` to `2025-09-18`: * [ ] Update bulk sync [create](/api-reference/bulk-sync/create) and [update](/api-reference/bulk-sync/update) payloads to use `default_schedule` and `additional_schedules`; remove any use of the `multi` schedule type. * [ ] Parse the new `default_schedule` / `additional_schedules` fields in bulk sync [list](/api-reference/bulk-sync/list) and [get](/api-reference/bulk-sync/get) responses. * [ ] Page through [`GET /api/syncs`](/api-reference/model-sync/list) using the `next_page_token` cursor, and switch to [`GET /api/syncs/{id}`](/api-reference/model-sync/get) for full sync configuration. * [ ] Route organization and user operations based on credential type (singular `/api/organization/...` for self, plural `/api/organizations/...` for partner). * [ ] Replace `POST .../share` with [`POST .../shared`](/api-reference/connections/create-shared-connection) for connection sharing, and update the parent path to the new partner-scoped form. * [ ] Replace `PUT /api/syncs/{sync_id}/executions/{id}` cancellations with [`POST .../cancel`](/api-reference/model-sync/executions/cancel). * [ ] If you used `GET /api/connections/{id}/modelsync/target`, switch to the [`target/fields`](/api-reference/model-sync/targets/get-fields) variant. You may also want to adopt the new capabilities described under [What's new](#whats-new): the [connection proxy](/api-reference/connections/execute-proxy), [entity lookup](/api-reference/entities/get), console log streaming for [model](/api-reference/model-sync/executions/get-console-logs) and [bulk](/api-reference/bulk-sync/executions/get-console-logs) sync executions, [schema-field patching](/api-reference/schemas/patch-field), and per-schedule resync modes on bulk syncs.