Skip to main content
The methods a custom integration uses, grouped by what they do. Full generated reference: gRPC API, API Scopes, OpenAPI spec. All services are under synq.entities.*. REST paths are given for the transcoded HTTP API; the same methods are available over gRPC.

Write

Types

synq.entities.custom.v1.TypesService Type carries type_id (11000), name (max 100 chars), svg_icon (max 1 MB) and traits.

Entities

synq.entities.custom.v1.EntitiesService Entity carries id, type_id, name (max 500 chars), description (max 10 000 chars, Markdown) and up to 20 annotations. Each annotation has a name (max 50 chars) and up to 20 values (max 100 chars each). synq_path, synq_catalog_url, ids and synq_paths are returned, never sent.

Features

synq.entities.custom.v1.FeaturesService A Feature is entity_id + feature_id (max 255 chars, stable) + one of: ListEntityFeatures with entity_id unset returns the features of every custom entity in the workspace.

Groups

synq.entities.custom.v1.GroupsService UpsertEntitiesGroup replaces the group’s membership whole and returns deleted_ids — the entities that were in the group and are not in this write.

Relationships

synq.entities.custom.v1.RelationshipsService Both writes return one RelationshipWriteResult per requested relationship, in request order, each with the resolved endpoints and an outcome of CREATED, UPDATED, DELETED or NOT_FOUND. At least one endpoint must be a custom entity.

Check relationships

synq.entities.custom.v1.ChecksRelationshipsService A CheckRelationship is check + checked + optional checked_columns. The pair is the identity; restating it with a different column list replaces the stored one.

Executions

synq.entities.custom.v1.EntityExecutionsService Execution requires id, status and created_at. Status is one of EXECUTION_STATUS_OK, _WARN, _ERROR, _CRITICAL. created_at must be in the past and later than 2022-01-01. extras can carry the executed SQL.

Read

Reading back is how you verify a write landed. These are the methods worth calling. BatchIdsByCoordinates is how you turn a warehouse name your tool reports into the entity id Coalesce Quality holds for it — useful when your tool names tables as strings. BatchResolveIdentifiers turns an identifier of any shape into its entity_id, and with check_existence: true reports whether the entity exists. It also returns the entity’s whole identity group — the other identifiers naming the same entity, such as a dbt model and the warehouse table it builds. Run it over the upstreams your integration is about to name. A custom entity that does not exist is rejected at the write, so you find that one either way; an entity on a connected platform is not checked and binds on next ingestion, so a typo’d warehouse name and a not-yet-crawled table look identical afterwards. Resolving separates them. The read methods above are meant to be driven from your integration as input, not only used to verify a write. Resolving coordinates, schemas and type numbers at run time is what keeps a mapping from drifting against a hardcoded table of ids.

Identifiers

A custom entity is named by CustomIdentifier:
The id is a slug, not a label: keep it to a lowercase A-Z a-z 0-9 : _ . - string built from the source system’s stable id, and put everything human-readable in name and description. On write it is truncated at 200 bytes with a hash tail if longer, non-ASCII is replaced by its literal escape text, and every other character is folded to _ — so two ids differing only in folded characters are the same entity, while ids differing only in case are two. The stored id is custom-<slug>. Entities from connected platforms are named by their platform’s own variant — bigquery_table, snowflake_table, databricks_table, postgres_table, mysql_table, clickhouse_table, redshift_table, trino_table, mssql_table, oracle_table, athena_table, fabric_table, dbt_core_node, dbt_cloud_node, sql_mesh_model, sql_mesh_audit, airflow_dag, airflow_task, monitor, dataproduct, saved_view. Prefer these wherever one exists for the platform. synq_path is the fallback variant, for a platform with no structured form — Looker, Tableau, Coalesce Catalog and anything added since — or for passing through an entity_id you already hold. Every identifier the API returns also carries entity_id, the entity’s opaque id, and it is the /catalog/<entity_id> segment of the entity’s app URL. It is output only: on a request it is ignored, and the structured variant is what resolves. To name an entity by opaque id on a request, put it in the synq_path variant. Ways to obtain an entity_id: the app URL after /catalog/, the MCP read tools, the entity_url in a webhook payload, or BatchIdsByCoordinates.

Enums

SqlDialectBIGQUERY, CLICKHOUSE, DATABRICKS, MYSQL, POSTGRESQL, REDSHIFT, SNOWFLAKE, DUCKDB, TRINO, MSSQL, ORACLE, ATHENA, FABRIC. CodeTypeSQL, PYTHON, JSON, YAML, DBT, SQLMESH, LOOKML, JAVASCRIPT, BASH, DAX, JAVA, SCALA, TEXT, MARKDOWN.

Pagination

The List* methods on the custom services take an optional Pagination. Omitting it, or sending a zero page_size, returns everything in one response — there is no server-side default page size. To page, set page_size and pass the previous response’s page_info.last_id as pagination.cursor, until last_id comes back empty. Not every list paginates: ListEntityTypeDefs, ListExecutionTypeDefs and ListPlatformDefs take no pagination at all and always return the full set.

Idempotency

Every Upsert* and Delete* method here is idempotent in effect: re-sending the same state converges on the same result, and deleting something that does not exist succeeds. It is not a no-op on the wire. An upsert always writes, restamping updated_at and re-triggering the fan-out that write implies, so a re-sync is not free — send it on a schedule, not in a tight loop.