Direct Data Share: Data Shape
Outbound Direct Data Share exports a fixed catalog of Benchling object types as tables. This page covers how those tables and columns are shaped, including schema field joins, and lists stable and beta object types, alphabetically, with whether each is available. See Direct Data Share: Outbound for how to connect and write basic queries against this data.
Outbound Data Shape
Tables mirror the V3 API object model
There is one table per shareable object type, named after the object type rather than after one of your schemas. Entry becomes ENTRY, DnaSequence becomes DNASEQUENCE, CustomEntity becomes CUSTOMENTITY. Columns are the object’s V3 API fields, so a field documented in the REST API reference is the field you get in SQL.
This means the table set is the same on every tenant. A query you write against CONTAINER keeps working when you add a new container schema. A dashboard built on ENTRY does not break when an entry schema is archived.
Identifier casing
Schema and table names are uppercase. Column names are not. Snowflake folds unquoted identifiers to uppercase, so:
- Schemas and tables need no quoting:
BENCHLING_TEN_ABC123.ENTRY - Columns almost always do:
"createdAt","schema_id","entityRegistryId"
Table aliases and output-column aliases do not need quoting, because Snowflake folds them consistently on both sides. SELECT e."name" AS entry_name FROM ... AS e is fine.
Field naming conventions
Direct Data Share flattens reference fields to IDs rather than nested objects, so you join to the referenced table yourself. There is no automatic denormalization. ENTRY."creator_id" gives you an ID, and USER."name" gives you the name.
Schema field values are separate tables
Your tenant-configured schema fields are not columns on the parent object’s table. They arrive as rows in a set of SCHEMAFIELDVALUE_<TYPE> tables, one per value type, each with the same shape:
The value type determines the table:
Benchling splits values by type, so each "value" column has one concrete SQL type. This keeps numeric and boolean fields queryable as numbers and booleans instead of strings. JSON and array payloads arrive as JSON strings; use Snowflake’s PARSE_JSON to read into them.
This is a key/value layout, so a schema field you think of as a column takes a join. Schema field joins below has worked examples, including how to pivot schema fields back into columns.
Archived records
Archived objects stay in the tables with "archived" set to true, and "archiveReason" set where the object type has one. Unless you are specifically auditing archived work, filter them out:
Timestamps are strings
"createdAt" and "modifiedAt" arrive as ISO-8601 text, not Snowflake TIMESTAMP. Wrap them before doing date arithmetic, truncation, or comparison against a timestamp:
ISO-8601 text happens to sort correctly, so a plain ORDER BY "createdAt" works. Do not rely on that for anything else.
Registry census
Registered entities carry "entityRegistryId" and "registry_id"; unregistered ones leave both null. This counts registered custom entities per schema and shows when each schema was last used:
Inventory with storage hierarchy
Containers point at their storage through "parentStorage_id", which can be a box, plate, or location. Joining to LOCATION keeps only the containers stored directly in a location:
Note "quantity_value" and "quantity_unit_id": a nested value object on the API becomes two prefixed columns. Group by the unit, or join to the unit table, before summing quantities across container types that use different units.
Schema field joins
Every SCHEMAFIELDVALUE_<TYPE> table joins back to its parent object and field definition the same way — see schema field values are separate tables. The examples below put that join to work.
Discover which fields exist
Before writing a field query, find the field definitions. "systemName" is the stable machine-readable identifier; "name" is what users see in the UI and can be renamed.
Read one field’s values by name
Join through the field definition so your query refers to the field by name instead of a hard-coded ID:
Pivot schema fields into columns
This is the query most teams want: one row per object, with named columns for the schema fields. The result looks like the table scientists see in Benchling.
Union the value tables into a single key/value stream, resolve each row’s field name, then pivot with conditional aggregation. Each new field you want is one more line in the SELECT:
Casting to STRING makes the union type-compatible. Cast back where you need arithmetic with TRY_TO_DECIMAL(titer_g_l) or TRY_TO_TIMESTAMP(thaw_date). Add SCHEMAFIELDVALUE_TEXTANDURL to the union if you use those fields; handle link fields separately, since their useful column is "value_id" rather than "value".
Resist the shortcut of joining several value tables directly to the parent table and keying each CASE on a single shared SCHEMAFIELDDEFINITION alias. If an object has two fields of the same type, the cross product pairs a field name with another field’s value. The pivot then silently reports the wrong value in the wrong column. Either resolve the field name on the same row as the value, as the union above does, or give each value table its own SCHEMAFIELDDEFINITION alias.
For a handful of fields you can skip the union and join each value table alongside its own field-definition alias, which keeps each name/value pair together:
Each additional value table multiplies rows before the GROUP BY collapses them, so prefer the union form once you are past a few fields.
Mirror one schema exactly
The pivot above hard-codes field names you already know. To reproduce a specific schema’s shape without guessing, first resolve which fields belong to it. SchemaFieldDefinition has no column pointing back to its parent schema, so go the other direction, through the schema’s fieldDefinitions_ids list.
Then feed the resulting field_system_name values into the pivot, scoping the parent table to the same schema so only entities of that type appear:
This covers scalar-valued fields only. A schema with link fields needs the value_id join from Follow entity link fields below instead. Link values live in OBJECTLINK/OBJECTLINKLIST, not in the scalar value tables unioned here. The same two-query shape works for any schema-bearing object type. Substitute the matching schema table (CONTAINERSCHEMA, ENTRYSCHEMA, and so on) and its parent table (CONTAINER, ENTRY) for CUSTOMENTITYSCHEMA and CUSTOMENTITY.
Follow entity link fields
Link fields are the interesting ones: they connect objects to each other, and they are how you walk from a result to the entity it measured. The linked object’s ID is in "value_id", so you join straight to the target table without parsing anything.
This reports assay results against the registered entity each one links to:
For multi-select link fields, use SCHEMAFIELDVALUE_OBJECTLINKLIST, where "value" holds a JSON array of IDs. Flatten it to get one row per link:
Join Benchling data to your own
The point of outbound sharing is joining Benchling records to data Benchling never had. With the share mounted in your own platform, that is an ordinary join.
This attaches your own process-history table to Benchling-registered batches, keyed on the registry ID your two systems share:
The registry ID is usually the best join key, because it is the identifier that appears on physical labels and in other systems. Benchling’s internal "id" works too, if your systems already exchange it.
Model coverage
106 of 236 object types are available.
A table only appears in your tenant’s schema once your tenant has at least one record of that type. Run SHOW TABLES against your schema to see what you actually have.
If a model you need is marked No, ask your Benchling representative whether it is on the roadmap.
Troubleshooting
invalid identifier 'CREATEDAT': you left a column name unquoted. Snowflake folded it to uppercase and the column is camelCase. Write "createdAt".
A table does not exist: tables appear only once there is at least one record of that type. Run SHOW TABLES to see what your tenant actually has. If an object type you do use is missing, check with your Benchling representative that it is in your share’s object list.
A schema field is missing from a pivot
Confirm which value table holds it. A field’s type determines its table, so a decimal field will not appear in SCHEMAFIELDVALUE_TEXT. Look up the field’s ID in SCHEMAFIELDDEFINITION, then search the value tables for it:
Fields explicitly cleared land in SCHEMAFIELDVALUE_NULL. For connection, authentication, and data-freshness issues, see Troubleshooting on the Outbound page.