Key-pair only, and unencrypted by necessity
How · Checked 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.
Integration · Warehouse
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.
How it works
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.
What you get
How · Checked 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.
How · written_rows, batches, failed_batches. Every batch failing returns 502 destination_write_failed with the warehouse’s own message.
How · GET /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.
How · normalizeSecretField() 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
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
The connector holds the key pair. The call carries a bearer token, an input and a destination id.
/v1/connectorsSave the connector. The secret is encrypted before it reaches Postgres.session/v1/connectors/{id}/schemaRead the target’s own columns — metadata only, never row data.bearer/v1/gatewayAny input in, this destination populated, a delivery report out.bearer/v1/connectors/{id}/rotate-secretReplace the credential in place; the old one becomes unrecoverable.sessionrole narrowly. AdaptivMapr holds a credential that writes into your warehouse; it should be able to do that and nothing more.dry_run reports 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
| 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. |
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.
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
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 and no subscription — 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
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.
Ready when you are
Start with a $10 prepaid wallet. Every map draws a few tokens; in schema-only mode only headers and a few sample rows ever leave you.