Model sync from MySQL to Snowflake

Set your Polytomic API key as an environment variable:

export POLYTOMIC_API_KEY=YOUR-API-TOKEN

This example covers three steps:

  1. Create a MySQL Connection.
  2. Create a model over a MySQL table.
  3. Create a sync to Snowflake.

1. Create a MySQL Connection

The following request creates a MySQL Connection. See the connection configuration reference for the required fields.

curl --request POST \
--url https://app.polytomic.com/api/connections \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}" \
-d '{
"name": "MySQL Connection",
"type": "mysql",
"configuration": {
"hostname": "localhost",
"port": 3306,
"dbname": "company",
"account": "user",
"passwd": "secret"
}
}'

2. Create a model

Next, create a model over the customers table on the MySQL Connection.

First, use the source endpoint to list the tables available on the Connection:

curl --request GET \
--url https://app.polytomic.com/api/connections/{YOUR-CONNECTION-ID}/modelsync/source \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}"

The response looks like:

{
"data": {
"items": {
"query": {
"items": null,
"requires_one_of": null,
"has_items": false
},
"table": {
"items": [
"company.accounts",
"company.customers",
"company.teams"
],
"requires_one_of": null,
"has_items": true
},
"tracking_columns": {
"items": null,
"requires_one_of": null,
"has_items": false
},
"view": {
"items": null,
"requires_one_of": null,
"has_items": false
}
},
"requires_one_of": [
"query",
"table",
"view"
]
}
}

Sources

Drill into each level with query parameters — for example, ?table=company.accounts. In this case, requires_one_of on table is null, so no further drill-down is needed.

Now create a model over company.customers:

curl --request POST \
--url https://app.polytomic.com/api/models \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}" \
-d '{
"name": "Customer Model",
"configuration": {
"table": "company.customers"
},
"connection_id": "YOUR-CONNECTION-ID"
}'

Replace YOUR-CONNECTION-ID with the Connection ID returned in Step 1.

3. Create a sync

Next, create a sync from the customer model to a new Snowflake target.

Create a target Connection

Create a Snowflake Connection to use as the sync target:

curl --request POST \
--url https://app.polytomic.com/api/connections \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}" \
-d '{
"name": "Snowflake Connection",
"type": "snowflake",
"configuration": {
"account": "account",
"dbname": "database",
"password": "secret-password",
"username": "user"
}
}'

Enumerate the target

Targets enumerate the same way sources do:

curl --request GET \
--url https://app.polytomic.com/api/connections/YOUR-CONNECTION-ID/modelsync/target \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}"

The response looks like:

{
"data": {
"items": {
"schema": {
"items": null,
"requires_one_of": [
"table",
"view"
],
"has_items": false
},
"table": {
"items": null,
"requires_one_of": null,
"has_items": false
},
"view": {
"items": null,
"requires_one_of": null,
"has_items": false
}
},
"requires_one_of": [
"schema"
]
}
}

Drill down recursively using the requires_one_of field. For example:

curl --request GET \
--url https://app.polytomic.com/api/connections/YOUR-CONNECTION-ID/modelsync/target?type=schema \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}"

The response looks like:

{
"data": {
"items": {
"schema": {
"items": [
"__pt_new_schema",
"CUSTOMERS",
"TEAMS"
],
"requires_one_of": [
"table"
],
"has_items": true
},
"table": {
"items": null,
"requires_one_of": null,
"has_items": false
}
},
"requires_one_of": [
"schema"
]
}
}

The schema level requires a table. Enumerate tables by adding another query parameter:

curl --request GET \
--url https://app.polytomic.com/api/connections/YOUR-CONNECTION-ID/modelsync/target?type=table&search=CUSTOMERS \
--header "accept: application/json" \
--header "content-type: application/json" \
--header "X-Polytomic-Version: 2025-09-18" \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}"

The response looks like:

{
"data": {
"items": {
"schema": {
"items": null,
"requires_one_of": [
"table"
],
"has_items": false
},
"table": {
"items": [
"__pt_new_target",
"CUSTOMERS.COMPANIES",
"CUSTOMERS.CONTACTS"
],
"requires_one_of": null,
"has_items": true
}
},
"requires_one_of": [
"schema"
]
}
}

Query target fields

Finally, query the available fields on the target. POST to the fields endpoint for the target resource:

curl --request POST \
--url https://app.polytomic.com/api/connections/YOUR-CONNECTION-ID/modelsync/target/fields \
--header 'X-Polytomic-Version: 2025-09-18' \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}" \
--header 'content-type: application/json' \
-d '{"target": "CUSTOMERS.CONTACTS"}'

The response lists the available sync modes and every field on the target along with its metadata. For example:

{
"data": {
"id": "CUSTOMERS.CONTACTS",
"name": "CUSTOMERS.CONTACTS",
"modes": [{
"mode": "create",
"description": "Create records when they don’t exist; don’t update existing ones",
"label": "Create",
"requires_identity": true,
"supports_target_filters": false,
"supports_field_sync_mode": false
},
{
"mode": "update",
"description": "Update existing records only; don’t create new ones",
"label": "Update",
"requires_identity": true,
"supports_target_filters": false,
"supports_field_sync_mode": false
},
{
"mode": "updateOrCreate",
"description": "Update records when they exist and create them when they don’t",
"label": "Update or Create",
"requires_identity": true,
"supports_target_filters": false,
"supports_field_sync_mode": false
},
{
"mode": "replace",
"description": "Replace all existing rows",
"label": "Replace",
"requires_identity": false,
"supports_target_filters": false,
"supports_field_sync_mode": false
},
{
"mode": "append",
"description": "Append rows to the end of the table",
"label": "Append",
"requires_identity": false,
"supports_target_filters": false,
"supports_field_sync_mode": false
}
],
"properties": {
"supports_field_creation": true
},
"refreshed_at": "0001-01-01T00:00:00Z",
"fields": [{
"id": "EMAIL",
"name": "EMAIL",
"description": "",
"required": false,
"filterable": false,
"createable": true,
"updateable": true,
"association": false,
"supports_identity": true,
"identity_functions": [
{
"id": "Equality",
"label": "Equality"
}
],
"source_type": "VARCHAR(16777216)",
"type": "string"
},
{
"id": "FIRST_NAME",
"name": "FIRST_NAME",
"description": "",
"required": false,
"filterable": false,
"createable": true,
"updateable": true,
"association": false,
"supports_identity": true,
"identity_functions": [
{
"id": "Equality",
"label": "Equality"
}
],
"source_type": "VARCHAR(16777216)",
"type": "string"
},
{
"id": "LAST_NAME",
"name": "LAST_NAME",
"description": "",
"required": false,
"filterable": false,
"createable": true,
"updateable": true,
"association": false,
"supports_identity": true,
"identity_functions": [
{
"id": "Equality",
"label": "Equality"
}
],
"source_type": "VARCHAR(16777216)",
"type": "string"
}
]
}
}

Create the sync

Map fields from the source model to the target and create the sync:

curl --request POST \
--url https://app.polytomic.com/api/syncs \
--header 'X-Polytomic-Version: 2025-09-18' \
--header "Authorization: Bearer ${POLYTOMIC_API_KEY}" \
--header 'content-type: application/json' \
--data '{
"name": "MySQL to Snowflake Sync",
"mode": "replace",
"fields": [
{
"source": {
"field": "email",
"model_id": "YOUR-SOURCE-MODEL-ID"
},
"target": "EMAIL"
},
{
"source": {
"field": "first_name",
"model_id": "YOUR-SOURCE-MODEL-ID"
},
"target": "FIRST_NAME"
},
{
"source": {
"field": "last_name",
"model_id": "YOUR-SOURCE-MODEL-ID"
},
"target": "LAST_NAME"
}
],
"schedule": {
"frequency": "continuous"
},
"target": {
"connection_id": "YOUR-TARGET-CONNECTION-ID",
"object": "CUSTOMERS.CONTACTS"
}
}'