# Create sync

URL: https://docs.hanzo.ai/docs/openapi/sync/post-sync

> Declares a sync between two endpoints and returns it.

`POST /v1/sync`

> [Sync →](https://docs.hanzo.ai/docs/openapi/sync) · [All API references →](https://docs.hanzo.ai/docs/openapi) · [Get started →](https://docs.hanzo.ai/docs/guides)

|               |                                        |
| ------------- | -------------------------------------- |
| **Address**   | `https://api.hanzo.ai/v1/sync`         |
| **Method**    | `POST`                                 |
| **Operation** | `post_sync`                            |
| **Auth**      | `Authorization: Bearer $HANZO_API_KEY` |

Declares a sync between two endpoints and returns it. It is an UPSERT:
re-declaring the same source and target updates that link rather than piling up
duplicates, so a console that re-submits is safe. The org comes from the validated
principal, never from the request, so a sync can only ever bind endpoints inside
the caller's own org. A git source must be an https clone URL on the provider's own
host with no embedded credentials; a target left empty is derived as a native
repository named after the source. A source naming only a GitHub account
(<https://github.com/&lt;account>>) links the whole account: every repository the org's
GitHub installation grants on it gets a repo link of its own, with this link's
direction and trigger, and so does every repository created there later. With run=true the first reconcile is queued in
the background, so a large initial import never blocks this response.

## Request

13 fields, body `application/json` (required).

| Field              | In   | Type             | Required | Description                                                                                               |
| ------------------ | ---- | ---------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `actor`            | body | string           | —        | Actor is the identity the sync writes as, used as the loop guard so its own writes do not re-trigger it.  |
| `direction`        | body | string           | —        | Direction is both (the default), pull, push or off.                                                       |
| `kind`             | body | string           | —        | Kind is what is being synced.                                                                             |
| `run`              | body | boolean          | —        | Run reconciles once immediately after the upsert, in the background.                                      |
| `source`           | body | sync.endpointReq | —        |                                                                                                           |
| `source.connector` | body | string           | —        | Connector names the stored credential to reach this endpoint with.                                        |
| `source.locator`   | body | string           | —        | Locator addresses the resource.                                                                           |
| `source.provider`  | body | string           | —        | Provider is the platform: github or gitlab for a source; a target defaults to the native Hanzo Git plane. |
| `target`           | body | sync.endpointReq | —        |                                                                                                           |
| `target.connector` | body | string           | —        | Connector names the stored credential to reach this endpoint with.                                        |
| `target.locator`   | body | string           | —        | Locator addresses the resource.                                                                           |
| `target.provider`  | body | string           | —        | Provider is the platform: github or gitlab for a source; a target defaults to the native Hanzo Git plane. |
| `trigger`          | body | string           | —        | Trigger is what starts a reconcile: webhook (the default), poll or manual.                                |

## Response

| Status    | Body            | Meaning |
| --------- | --------------- | ------- |
| `200`     | sync.syncView   | ok      |
| `default` | problem-details | refused |

`200` body — 24 fields.

| Field               | In   | Type              | Always | Description                                                                                                                                                                                                                               |
| ------------------- | ---- | ----------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actor`             | body | string            | —      | Actor is the identity a reconcile writes AS.                                                                                                                                                                                              |
| `createdAt`         | body | string            | —      | CreatedAt is when the link was first declared, RFC3339 in UTC.                                                                                                                                                                            |
| `direction`         | body | string            | —      | Direction is which way work flows: "both", "pull" (target ← source), "push" (source → target), or "off" — which keeps the link declared and moves nothing.                                                                                |
| `id`                | body | string            | —      | ID is the link's handle, derived from its source and target — which is what makes re-declaring the same pair an update rather than a duplicate.                                                                                           |
| `kind`              | body | string            | —      | Kind is what is being synced.                                                                                                                                                                                                             |
| `native`            | body | sync.nativeView   | —      |                                                                                                                                                                                                                                           |
| `native.advancedAt` | body | string            | —      | AdvancedAt is when an import or a push last moved one of its refs, RFC3339 in UTC.                                                                                                                                                        |
| `native.branch`     | body | string            | —      | Branch is the forge's default branch, which an import sets to the upstream's once that branch has landed.                                                                                                                                 |
| `native.clone`      | body | string            | —      | Clone is the https address to clone it from.                                                                                                                                                                                              |
| `native.sizeBytes`  | body | integer (int64)   | —      | SizeBytes is the repository's size on the forge, in bytes.                                                                                                                                                                                |
| `native.ssh`        | body | string            | —      | SSH is the ssh address to clone it from, when the forge serves one.                                                                                                                                                                       |
| `native.status`     | body | string            | —      | Status is one of "synced" (the forge holds it and no ref is in conflict), "conflict" (an upstream ref diverged and the forge kept its own history), "pending" (the forge does not hold it yet) or "paused" (the link's direction is off). |
| `native.url`        | body | string            | —      | URL is the repository's page on the forge.                                                                                                                                                                                                |
| `scope`             | body | string            | —      | Scope is "repo" for a link to one repository, or "account" for a link to a whole GitHub account, which declares a repo link for every repository the account holds — the ones created later included.                                     |
| `source`            | body | sync.endpointView | —      |                                                                                                                                                                                                                                           |
| `source.connector`  | body | string            | —      | Connector names a connected account from the org's connector registry, when the endpoint reaches its provider through one.                                                                                                                |
| `source.locator`    | body | string            | —      | Locator addresses the thing INSIDE that provider, in the provider's own terms — an https clone URL for a hosted forge, a bare repository name for hanzo-git.                                                                              |
| `source.provider`   | body | string            | —      | Provider is the concrete integration: "github", "gitlab" or "hanzo-git".                                                                                                                                                                  |
| `target`            | body | sync.endpointView | —      |                                                                                                                                                                                                                                           |
| `target.connector`  | body | string            | —      | Connector names a connected account from the org's connector registry, when the endpoint reaches its provider through one.                                                                                                                |
| `target.locator`    | body | string            | —      | Locator addresses the thing INSIDE that provider, in the provider's own terms — an https clone URL for a hosted forge, a bare repository name for hanzo-git.                                                                              |
| `target.provider`   | body | string            | —      | Provider is the concrete integration: "github", "gitlab" or "hanzo-git".                                                                                                                                                                  |
| `trigger`           | body | string            | —      | Trigger is what starts a reconcile: "webhook" (the provider tells us), "poll" (we ask on a schedule), or "manual" (only an explicit call).                                                                                                |
| `updatedAt`         | body | string            | —      | UpdatedAt is bumped by every reconcile, so it reads as the LAST-SYNCED time rather than the last edit.                                                                                                                                    |

Failure carries the platform error shape — see [Errors](https://docs.hanzo.ai/docs/errors).

## Examples

**CLI**

```bash
hanzo sync create
```

**SDK**

**.ts**

```ts
import { Configuration, SyncApi } from 'hanzoai';

const api = new SyncApi(new Configuration({ accessToken: process.env.HANZO_API_KEY }));
const { data } = await api.postSync({ actor: "<actor>", direction: "<direction>" });
```

**.py**

```python
from hanzoai.cloud import ApiClient, Configuration
from hanzoai.cloud.api import SyncApi

client = ApiClient(Configuration(access_token=os.environ["HANZO_API_KEY"]))
result = SyncApi(client).post_sync(actor="<actor>", direction="<direction>")
```

**.go**

```go
cfg := hanzoai.NewConfiguration()
cfg.AddDefaultHeader("Authorization", "Bearer "+os.Getenv("HANZO_API_KEY"))
client := hanzoai.NewAPIClient(cfg)

resp, _, err := client.SyncAPI.PostSync(context.Background()).Execute()
if err != nil {
	return err
}
```

**.rs**

```rust
use hanzo_client::apis::{configuration::Configuration, sync_api};

let mut cfg = Configuration::new();
cfg.bearer_access_token = std::env::var("HANZO_API_KEY").ok();

let result = sync_api::post_sync(&cfg, Default::default()).await?;
```

**.java**

```java
import ai.hanzo.cloud.ApiClient;
import ai.hanzo.cloud.api.SyncApi;

ApiClient client = new ApiClient();
client.setBearerToken(System.getenv("HANZO_API_KEY"));

var result = new SyncApi(client).postSync();
```

**HTTP**

```bash
curl -X POST https://api.hanzo.ai/v1/sync \
  -H "Authorization: Bearer $HANZO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
       "actor": "<actor>",
       "direction": "<direction>"
     }'
```

**MCP**

MCP reaches **sync** through the `sync` tool, which names its 6 operations with its own verbs — this one among them, under a name only MCP declares. `describe` explains any of them:

```bash
curl -X POST https://api.hanzo.ai/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{
       "jsonrpc": "2.0",
       "id": 1,
       "method": "tools/call",
       "params": {
         "name": "describe",
         "arguments": {
           "op": "list_syncs"
         }
       }
     }'
```

---

[Sync API](https://docs.hanzo.ai/docs/openapi/sync) · [All Hanzo APIs](https://docs.hanzo.ai/docs/openapi) · [Interactive reference](https://docs.hanzo.ai/docs/openapi/reference)
