Integration · Warehouse
Key-pair auth, no password anywhere.
Mapped rows are written through Snowflake’s SQL Statement API in batches of 500, authenticated with a key-pair JWT. Passwords are not accepted, and neither is an encrypted key.
- Method
- POST
- Connector kind
- 1
How it works
What actually happens on a sync run
Snowflake is reached through its SQL Statement API — POST https://<account>.snowflakecomputing.com/api/v2/statements — authenticated with a key-pair JWT. Passwords are refused at save time, and so is an encrypted private key: a Worker has nowhere safe to hold a passphrase, and accepting one would be pretending otherwise. Rows go in batches of 500 with every identifier validated before a statement is built.
- 1
Sign a JWT
The unencrypted PEM private key signs a short-lived JWT bound to the account and user. - 2
Resolve the target
Database, schema, warehouse and role are sent alongside the statement; the table may be dotted. - 3
Send batched statements
500 rows per statement, each batch independent. - 4
Report per batch
Failed batch indices are named; every batch failing is a loud error, not a quiet success.
What you get
Built for files that keep arriving
Auth
Key-pair only, and unencrypted by necessity
Snowflake key-pair auth is the supported mechanism. A password is refused; an encrypted key is refused with an explicit reason rather than accepted and then quietly unusable.
HowChecked at create: the value must contain PRIVATE KEY and must not be ENCRYPTED PRIVATE KEY. A Worker has nowhere safe to hold a passphrase, and saying so is better than implying it does.
Write
Bounded batches, named failures
500 rows per statement so one bad batch cannot take a whole delivery with it, and the report says which indices failed.
Howwritten_rows, batches, failed_batches. Every batch failing returns 502 destination_write_failed with the warehouse’s own message.
Schema
The table’s own columns, read not restated
A gateway call maps onto the real columns. Restating a schema in the request would create a second source of truth that drifts the moment someone adds a column.
HowGET /v1/connectors/{id}/schema returns the column list and a template. Naming a column that does not exist fails 422 schema_destination_mismatch before any write.
Secrets
The credential never travels in a request body
You reference a connector by id. Keys, tokens and service-account JSON are encrypted at rest and read only by the code that makes the call.
HownormalizeSecretField() folds every provider spelling — private_key, token, secret_access_key, account_key, service_account_json — into one auth_value field, which is KEK-envelope-encrypted before the row is written. A GET masks it to a 4-character hint. If encryption fails the field is dropped rather than stored in plaintext.
Configuration
The connector record, field by field
A password is not an accepted credential here and an encrypted key is refused with the reason. Both checks run at save time, so the connector that exists is one that can actually authenticate.
| Key | Required | What it is |
|---|---|---|
| account | Required | Snowflake account identifier. Required, checked at save time. |
| user | Required | The user the key pair belongs to. |
| auth_valuesecret | Required | An UNENCRYPTED PEM private key. A value without PRIVATE KEY is refused; so is ENCRYPTED PRIVATE KEY. |
| public_key_fingerprint | Optional | Fingerprint for the JWT’s issuer claim, when your account requires it. |
| table | Optional | Target table, optionally dotted. Overridable per call with destination.table. |
| database | Optional | Database context for the statement. |
| schema | Optional | Schema context for the statement. |
| warehouse | Optional | Warehouse to run on. |
| role | Optional | Role to assume — the place to scope what the credential can do. |
| host | Optional | Override the derived <account>.snowflakecomputing.com host. |
In code
A messy export in, a clean load out.
The connector holds the key pair. The call carries a bearer token, an input and a destination id.
- POST
/v1/connectorsSave the connector. The secret is encrypted before it reaches Postgres.session - GET
/v1/connectors/{id}/schemaRead the target’s own columns — metadata only, never row data.bearer - POST
/v1/gatewayAny input in, this destination populated, a delivery report out.bearer - POST
/v1/connectors/{id}/rotate-secretReplace the credential in place; the old one becomes unrecoverable.session
- Scope the
rolenarrowly. AdaptivMapr holds a credential that writes into your warehouse; it should be able to do that and nothing more. - Identifiers are validated before a statement is built, so a table name that would have to be rewritten is refused instead of reshaped.
dry_runreports the batch count without executing anything.
{
"kind": "snowflake",
"name": "Finance warehouse",
"config": {
"account": "acme-eu_central",
"user": "MAPR_LOADER",
"database": "FINANCE",
"schema": "RAW",
"warehouse": "LOAD_WH",
"role": "MAPR_WRITER",
"table": "INVOICES",
"private_key": "-----BEGIN PRIVATE KEY-----\n…"
}
}curl https://api.adaptivmapr.com/v1/gateway \
-H "Authorization: Bearer $MAPR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"input": { "connector_id": "con_4a91…" },
"destination": { "connector_id": "con_77de…", "table": "FINANCE.RAW.INVOICES" }
}'{
"schema_id": "invoices_v1",
"source": "destination",
"row_count": 2400,
"destination": {
"connector_id": "con_77de…",
"kind": "snowflake",
"table": "FINANCE.RAW.INVOICES",
"schema_source": "destination",
"protocol": "snowflake",
"written_rows": 2400,
"batches": 5,
"failed_batches": []
}
}Limits & failure modes
What it refuses, and what it tells you
| Code | When | What to do |
|---|---|---|
400 config_invalid | A password was supplied, or the key is encrypted, or account/user is missing. | All three are checked at save time with an explicit message naming which one. |
400 config_invalid (identifier) | The table is not an identifier, optionally dotted. | Refused rather than silently rewritten at write time. |
502 destination_write_failed | Every batch was rejected. | Surfaced with Snowflake’s own message — a permission error and a type error need different fixes. |
422 schema_destination_mismatch | A supplied schema names a column the table does not have. | Pre-flight catches it before the first statement runs. |
Incremental sync
Not applicable: Snowflake is a destination here. To pull FROM a warehouse on a cadence, expose the query behind an HTTPS endpoint and use the SQL-over-HTTP source, which supports a {{since}} watermark.
PHI & residency
X-PHI and X-Region to phi-cloud so a regulated run lands on an in-region, BAA-eligible model, it costs +20% on the whole charge, and it is locked until the workspace accepts the BAA in Settings → Security & Data. An explicit PHI ask without an acceptance is 403 agreement_required, never a silent downgrade. A standard run keeps the workspace’s region pin — the region decides where compute may run, and the sandbox refuses a region-less run.What it costs
Billed on the same prepaid wallet
Moving bytes is not a line item. A sync that pulls a file and a destination write that lands the rows are both part of one map, and the map is what the wallet sees. There is no free tier, no seats and no contract — top up from $10, a balance shared across the phi-cloud suite.
| Charge | Rate | Notes |
|---|---|---|
| Every map | $0.001 | A flat per-map fee — a few tokens — charged even when the run was fully deterministic or hit the layout cache and used no AI at all. |
| AI, only when it ran | at cost × 2 | Layer-5 cleanup, any-to-any convert and structural reshape bill the phi-cloud tokens actually consumed. Bring your own model key and it is × 0.5. |
| PHI / enterprise routing | +20% | Multiplies the whole charge, flat fee included — and only when the run genuinely got that routing. Locked until the workspace accepts the BAA in-app. |
Questions
Before you wire it up
Why will you not accept a Snowflake password?
How do I limit what the credential can do?
What happens if one batch fails?
Can I try it without writing?
Verified against lib/warehouseSql.ts · lib/destinations.ts · lib/introspect.ts · app/api/v1/connectors/route.ts
Snowflake is a trademark of Snowflake Inc. Named here to describe interoperability only — no affiliation, endorsement or partnership is claimed.
Point it at Snowflake. Get your schema back.
Start with a $10 prepaid wallet. Every map draws a few tokens; in schema-only mode only headers and up to three sample rows, clamped to 80 characters a cell, ever leave you.