Skip to content

The manifest and submission payload

This page is a developer reference, for someone writing their own renderer against Sliick Forms rather than embedding the hosted one. See The Sliick Forms REST API for how a caller authenticates.

Every consumer should locate a form by formExternalId, never by Salesforce record ID. It is the same identifier blueprint import and export use, so it is stable across environments.

The read surface returns one experience bundle:

KeyWhat it is
experienceIdThe form’s external ID
formNameThe form’s name
schemaVersionCurrently sliick-1
rootThe form as a node tree
metaprovider, formFound, guestEnabled, and the resolved theme tokens

Every node in root is { definition, attributes, children, meta, events }. Definitions use tile/* where the node is semantically valid as-is (tile/textfield, tile/select, tile/checkbox, tile/radio, tile/numberfield, tile/textarea, tile/column) and sliick/* for Sliick extensions (sliick/page, sliick/section, sliick/repeat, sliick/rating, sliick/date, sliick/datetime, sliick/secure-upload).

Visibility rules ride on meta.if and are evaluated by the client against live field values; the server re-evaluates them at submit. Repeating groups carry iteration directives (meta.forEach, meta.forItem) with their row template as children, and their payload key is an array of row objects.

The tree is the canonical schema for the rendered form. Do not reconstruct fields from Salesforce metadata independently.

{
  "experienceId": "support-intake",
  "formName": "Support Intake",
  "schemaVersion": "Sliick-1",
  "meta": { "provider": "Sliick", "formFound": true, "guestEnabled": true,
            "theme": { "brandPrimary": "#1B76D1", "cornerRadius": "0.375rem" } },
  "root": {
    "type": "mosaic",
    "definition": "tile/mosaic",
    "children": [
      {
        "definition": "tile/textfield",
        "attributes": { "name": "email", "label": "Email", "required": true,
                        "inputType": "email", "pattern": ".+@.+" },
        "meta": { "elementType": "Email", "order": 1 }
      }
    ]
  }
}

Bound-attribute names to read carefully. A repeating group’s row-count bounds are minRows and maxRows on the wire, because minLength and maxLength mean character-length bounds on text inputs. A Date or Date/Time element’s day-offset bounds are minDaysFromToday and maxDaysFromToday, because min and max mean numeric value bounds on Number, Currency and Rating. Only the manifest attributes carry these names: blueprint import and export are unaffected.

Every runtime surface submits the same shape:

{
  "formExternalId": "support-intake",
  "correlationId": "web-12345",
  "sourceChannel": "web",
  "payload": {
    "email": "casey@example.com",
    "issueSummary": "Cannot access account"
  }
}

A repeating group’s payload key is an array of row objects, and a repeating group nested inside another appears as an array under that row’s own key, not flattened to the top level:

{
  "formExternalId": "line-item-intake",
  "payload": {
    "orders": [
      {
        "customer_name": "Acme Co",
        "line_items": [
          { "sku": "A100", "qty": 2 },
          { "sku": "B200", "qty": 1 }
        ]
      }
    ]
  }
}

Each nested row’s parent is the specific outer row it was authored under: processing creates child records under the correct parent for that row, not one shared parent for the whole group.

The staged response and the record are not the same thing. An element whose effective visibility is false against the submitted answers, whether from its own rule or from any ancestor page, section, row or repeat, contributes nothing at processing, even if the payload includes a value for it.

  1. The staged envelope is the unstripped audit record. It stores exactly what arrived over the wire.
  2. Processing is where the strip is enforced. A crafted or stale payload naming an author-hidden field stages fine and never reaches the mapped record.
  3. Hidden-type elements are exempt, unconditionally. A mapped Hidden element with a default value is stamped at processing even when the payload omits the key. This is the only case where a default survives an absent key: a visible field’s default that a respondent cleared stays cleared.
  4. A hidden repeating group contributes zero child rows, and a visible one strips per row and per field, recursing into nested groups against each row’s own context.
  5. File uploads follow the same rule. A file uploaded inside a rule-hidden branch is never linked to the record, even though the upload succeeded.

Well-behaved clients omit rule-hidden values from the payload in the first place, so for an honest client the payload already equals what the review screen showed. Build yours the same way: do not rely on the server to clean up a payload containing answers the respondent never saw, because it drops them from the record and preserves them only in the staging audit trail.

None of the enforcement lives in the JavaScript, so a hand-crafted payload gains a caller nothing. Server-side, every submission is checked for the honeypot field, the form’s availability, required fields, patterns, lengths and ranges, and visibility resolution is re-run so values for elements the respondent never saw do not slip through. If the form’s elements cannot be read to validate against, the submission is refused, not accepted unvalidated. Payload keys that do not correspond to a mapped element go nowhere: the processor writes only through each element’s mapping.