Entering & approving data
The day-to-day workflow: an editor submits a row, Normly validates it, and an approver signs it off — or sends it back with a reason.
Row lifecycle
Every row moves through a simple set of states:
| Status | Meaning | Who acts next |
|---|---|---|
| Pending | Submitted and waiting for sign-off. Not yet part of official data. | An approver |
| Approved | Signed off. This is the data that reports, exports, and the API return. | — |
| Rejected | Sent back with a mandatory reason explaining what to fix. | The editor, who corrects and resubmits |
Entering data
Open the table and add a row: one value per column. Required columns must be filled, and values must match the column's data type. When you submit, the row appears as pending for the table's approvers.
Validation
Columns can carry validation rules set by the table designer. Normly flags rows whose values no longer pass validation, and editors see these flagged rows on their dashboard so problems surface early — before an approver ever looks at them.
Approving and rejecting
Approvers see pending rows on their dashboard and on the table itself, with the submitted values and who entered them. Approving marks the row as official, recording who approved it and when. Rejecting requires a reason, which the editor sees next to the returned row.
- On: the approver must be a different person from the submitter, with no exceptions.
- Off (the default): rows entered by someone who may also approve — a combined editor-approver or a company admin — are approved straight away, marked as approved automatically in the audit trail. Rows from editors who can't approve still wait for an approver.
The audit trail
Each row keeps its history: who created it, when, who approved or rejected it, and why. Combined with table versioning, this means you can always answer "who signed off on this number, and against which definition?"
Automating the workflow
Everything on this page can also be done programmatically — listing pending rows, approving, and rejecting with a reason. See the API reference for runnable examples.