> For the complete documentation index, see [llms.txt](https://docs.openiam.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.openiam.com/developer-guide/synchronization.md).

# Driving synchronization

The synchronization configuration API — manage configurations, test and run them, and work with CSV sources, including the two base paths that catch people out.

## What this covers

|                |                                                                                                                       |
| -------------- | --------------------------------------------------------------------------------------------------------------------- |
| **You get**    | The operations that manage synchronization configurations, run them, and handle CSV sources                           |
| **You need**   | A token — [*API fundamentals*](/developer-guide/fundamentals.md) — and a caller allowed to administer synchronization |
| **Base paths** | **Two.** `/rest/api/syncconfig` for configurations, `/rest/api/csv` for CSV file operations                           |
| **Method**     | Mostly `GET`; `POST`/`PUT` to save, `DELETE` to remove                                                                |

## Before you start

* **A token**, and a client whose scopes cover `/rest/api/syncconfig` and `/rest/api/csv`.
* **A test deployment for your first attempts.** Starting a synchronization reads a real source and writes real identities, and the run propagates to connected systems.
* **A configuration to work against.** These operations manage and run configurations; they do not design one for you. [*Set up a synchronization*](/administration-guide/lifecycle/synchronize-and-import-data.md) covers what a configuration needs to contain before it is worth running.

## Set these first

```bash
export OPENIAM_URL=<the address your deployment is published on>
export TOKEN=<a bearer token>
```

***

## The two base paths

**This is the thing to get right first.** Configuration operations live under `/rest/api/syncconfig`, but the CSV file operations do **not** — they live under `/rest/api/csv`, with the identifier before the verb:

```
/rest/api/csv/{id}/download        not  /rest/api/syncconfig/csv/get/{id}
/rest/api/csv/{id}/preview         not  /rest/api/syncconfig/csv/preview/{id}
/rest/api/csv/findAll              not  /rest/api/syncconfig/csv/list
```

The forms on the right do not exist. A call to one returns a 404 that looks exactly like "no such configuration", so it is easy to spend a while blaming the identifier rather than the path.

The one exception is **upload**, which is a configuration operation and stays under `/rest/api/syncconfig`.

## Managing configurations

| Operation                                 | Returns                                             |
| ----------------------------------------- | --------------------------------------------------- |
| `GET /rest/api/syncconfig/get/{id}`       | `SynchConfigResponse` — one configuration           |
| `GET /rest/api/syncconfig/search`         | `BeanResponse` — configurations matching the search |
| `POST /rest/api/syncconfig/save`          | `BasicAjaxResponse`                                 |
| `PUT /rest/api/syncconfig/save`           | `BasicAjaxResponse`                                 |
| `DELETE /rest/api/syncconfig/delete/{id}` | `BasicAjaxResponse`                                 |

The bodies these take are defined in your deployment's own API specification, which is the authoritative source for field names — see [*API fundamentals*](/developer-guide/fundamentals.md) for how to reach it.

## Testing and running

| Operation                                   | Does                                                               |
| ------------------------------------------- | ------------------------------------------------------------------ |
| `GET /rest/api/syncconfig/{id}/testConnect` | Checks the configured source is reachable, without reading records |
| `GET /rest/api/syncconfig/{id}/startSynch`  | Starts the run                                                     |

**Run `testConnect` first.** It is the cheap way to separate "the source is unreachable" from "the source is fine but the configuration is wrong", and it changes nothing.

{% hint style="warning" %}
`startSynch` returns as soon as the run is **accepted**, not when it finishes. A `200` means the run started, not that it succeeded — read the outcome from the run history rather than the response. [*Set up a synchronization*](/administration-guide/lifecycle/synchronize-and-import-data.md) covers the audit events and per-record results a run produces.
{% endhint %}

## Working with CSV sources

| Operation                          | Returns                                                                |
| ---------------------------------- | ---------------------------------------------------------------------- |
| `POST /rest/api/syncconfig/upload` | `BasicAjaxResponse` — uploads a CSV against a configuration            |
| `GET /rest/api/csv/findAll`        | `CSVConfigListResponse` — every stored CSV configuration               |
| `GET /rest/api/csv/{id}/preview`   | `BasicAjaxResponse` — the stored preview, parsed into rows and columns |
| `GET /rest/api/csv/{id}/download`  | `text/csv;charset=UTF-8` — the stored file itself                      |

### Preview uses the configured splitter

`preview` parses the stored preview into rows and columns using the **splitter configured on the associated synchronization configuration**, falling back to a comma when none is set.

That fallback is worth knowing about. A semicolon- or tab-delimited file whose configuration has no splitter set previews as a **single column per row** — the data is intact and the parse is doing exactly what it was told, but the preview looks wrong. Set the splitter on the configuration, then preview again.

### Download returns a file, not JSON

`download` returns the stored configuration as a file rather than a JSON envelope. The body is sent as UTF-8 and the response declares that charset, so names and values outside ASCII survive the round trip intact. The file is named after the configuration — which is the name of the file it was uploaded from — with a `.csv` extension.

Handle it as a download rather than parsing it as an API response:

```bash
curl -sS -H "Authorization: Bearer $TOKEN" \
  -OJ "$OPENIAM_URL/rest/api/csv/{id}/download"
```

## Reading the result

Most operations here return `BasicAjaxResponse`, which reports whether the call succeeded rather than describing what changed. For anything that alters data, confirm the effect rather than trusting the envelope:

* **After an upload**, a `SYNCHRONIZATION_CSV_FILE_ATTACHED` audit entry records the file name, its size, the stored line count and the configuration identifiers. The line count excludes blank lines, so expect it to differ from the file on disk.
* **After a run**, read the run history rather than the `startSynch` response.

## If it goes wrong

| Symptom                                         | Usually                                                                                   |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------- |
| `404` on a CSV operation                        | The old `/rest/api/syncconfig/csv/...` path. Check the base path before the identifier    |
| Preview shows one column per row                | No splitter set on the configuration, so it fell back to a comma                          |
| Downloaded file has mangled characters          | The client ignored the declared charset — the response is UTF-8                           |
| `startSynch` returned `200` but nothing changed | The run was accepted and then failed. The outcome is in the run history, not the response |

## What this does not cover

Designing a synchronization — matching rules, transformation scripts, provisioning behaviour — is administration rather than API work. See [*Set up a synchronization*](/administration-guide/lifecycle/synchronize-and-import-data.md) and [*How a synchronization matches and processes a record*](/administration-guide/lifecycle/synchronize-and-import-data/synchronization-matching-and-processing.md).

## Related

* [*API fundamentals*](/developer-guide/fundamentals.md) — tokens, base URLs, and reaching your deployment's specification
* [*Set up a synchronization*](/administration-guide/lifecycle/synchronize-and-import-data.md) — building and verifying a configuration
* [*How a synchronization matches and processes a record*](/administration-guide/lifecycle/synchronize-and-import-data/synchronization-matching-and-processing.md) — matching, and the codes a dropped record carries
* [*Common errors*](/developer-guide/common-errors.md) — responses shared across the API


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.openiam.com/developer-guide/synchronization.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
