---
title: "Signing status and record updates"
url: "https://docs.signnow.com/docs/salesforce-signing-status-and-record-updates"
type: "page"
section: "Integrations"
slug: "salesforce-signing-status-and-record-updates"
---

# Signing status and record updates

# Signing status and record updates

SignNow writes invite and signer statuses into your Salesforce org as records you can query, report on and trigger flows from. For example, move an Opportunity to **Closed Won** when a contract is signed.

Status reaches your org in two forms:

| Mechanism | API name | Use it for |
| --- | --- | --- |
| Custom object, invite level | `cuda_signnow__SignNow_Invitation__c` | Reporting on invites; resolving the Salesforce record an invite was sent from |
| Custom object, recipient level | `cuda_signnow__SignNow_Signer__c` | Reacting to an individual recipient; branching on signing order |
| Platform event | `cuda_signnow__SignNow_Event__e` | Reacting the moment an invite changes state, without querying records |

The records persist. You can query them, build reports on them, and test a flow against invites your org has already sent. The platform event does not persist: it carries invite-level facts at the moment a change happens, which suits a flow that only needs to react. See [SignNow Invite Status Update event](https://docs.signnow.com/docs/apex-invite-status-update-event) for its payload and behavior.

The [Invites Status widget](https://docs.signnow.com/docs/salesforce-invites-status-widget) shows these statuses live from SignNow on a record page, for people to read. Automation runs on the records and the event.

## SignNow Invitation

The SignNow for Salesforce package installs two custom objects for status. **SignNow Invitation** is the first. Each time a document is sent for signature from a Salesforce record, SignNow creates one SignNow Invitation record and keeps it updated as the invite progresses. The record represents the invite as a whole and stores which Salesforce record it was sent from.

| Field | API name | Type | Description |
| --- | --- | --- | --- |
| Context ID | `cuda_signnow__Context_ID__c` | Text(255) | ID of the Salesforce record the invite was sent from |
| Context Table | `cuda_signnow__Context_Table__c` | Text(255) | API name of that record's object, for example `Opportunity` |
| Status | `cuda_signnow__Status__c` | Text(255) | The invite's current state |
| Document ID | `cuda_signnow__Document_ID__c` | Text(255), External ID | The SignNow document the invite was sent for |
| Document Name | `cuda_signnow__Document_Name__c` | Text(255) | Name of that document |
| Template ID | `cuda_signnow__Template_ID__c` | Text(255), External ID | The template the document was created from, if any |
| Template Name | `cuda_signnow__Template_Name__c` | Text(255) | Name of that template |
| SN User Email | `cuda_signnow__SN_User_Email__c` | Email | Email of the SignNow user who sent the invite |
| SN User ID | `cuda_signnow__SN_User_ID__c` | Text(255), External ID | That user's SignNow ID |
| User ID | `cuda_signnow__User_ID__c` | Text(255) | The Salesforce user who sent the invite |
| SignNow Invitation Name | `Name` | Auto Number | Record name |

In Setup, open **Object Manager > SignNow Invitation > Fields & Relationships** to see the same list in your own org:

![signnow_invitation_fields.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/signnow_invitation_fields.png)

Match **Context ID** against the ID of the record you want to update. That is how a flow resolves the right Opportunity. Check **Context Table** alongside it, so a flow built for Opportunities does not act on an invite sent from an Account.

**Status values:**

| Value | Meaning |
| --- | --- |
| `Draft` | The invite has been created but not sent, or has been cancelled |
| `Pending` | The invite has been sent and is awaiting recipients |
| `Signed` | The invite is complete |
| `Declined` | A recipient declined to sign |
| `Expired` | The invite expired |

> [!NOTE]
> `Status` is a text field rather than a picklist, so Salesforce does not constrain its values. SignNow writes the Title Case values above. A lowercase value such as `init` or `fulfilled` is an unmapped status arriving straight from the API, so match on the Title Case form and treat a lowercase one as its equivalent. To list every value present in your own org:
>
> ```sql
> SELECT cuda_signnow__Status__c, COUNT(Id)
> FROM cuda_signnow__SignNow_Invitation__c
> GROUP BY cuda_signnow__Status__c
> ```

## SignNow Signer

**SignNow Signer** is the second object. SignNow creates one SignNow Signer record for each recipient on an invite, so a document sent to three people produces three records. Each one belongs to its SignNow Invitation through a master-detail relationship, and carries that recipient's own status and position in the signing order.

| Field | API name | Type | Description |
| --- | --- | --- | --- |
| Status | `cuda_signnow__Status__c` | Text(255) | The recipient's current state |
| Order | `cuda_signnow__Order__c` | Number(18, 0) | The recipient's position in the signing order, starting at 1 |
| Email | `cuda_signnow__Email__c` | Email | The recipient's email address |
| SignNow Invitation | `cuda_signnow__SignNow_Invitation__c` | Master-Detail | The invite this recipient belongs to |
| SignNow Signer Name | `Name` | Auto Number | Record name |

![signnow_signer_fields.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/signnow_signer_fields.png)

Those five fields, plus `CreatedById` and `LastModifiedById`, are everything SignNow Signer holds. Two consequences follow:

- **The signer record carries no Context ID.** To reach the Opportunity from a signer, traverse the master-detail relationship to the parent invitation and read **Context ID** there.
- **There is no signing timestamp field.** For the moment a recipient completed, use the platform event's timestamp or the record's `LastModifiedDate`, accepting that any later write moves it.

**Status values:**

| Value | Meaning |
| --- | --- |
| `Pending` | The invite has been sent to the recipient and is awaiting action |
| `Invite Step Pending` | An earlier signing step is still open, so this recipient cannot act yet |
| `Signed` | The recipient completed the document |
| `Declined` | The recipient declined to sign |
| `View Only` | The recipient received the document as view-only |
| `Expired` | The invite expired before the recipient acted |

Those are all six values SignNow writes for a recipient. As with the invitation, the field is free text, so a lowercase value is an unmapped API status. To list every value present in your own org:

```sql
SELECT cuda_signnow__Status__c, COUNT(Id)
FROM cuda_signnow__SignNow_Signer__c
GROUP BY cuda_signnow__Status__c
```

![signer_status_values.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/signer_status_values.png)

On both objects `Status` is a `Text(255)` field rather than a picklist, so Salesforce does not constrain its values and the field definition in Setup shows no value set. Match the strings exactly, including capitalization and spaces:

![signnow_signer_status_field.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/signnow_signer_status_field.png)

> [!WARNING]
> Build conditions on the field values, not on what the Invites Status widget displays. The widget uses its own labels: *Completed* where the record holds `Signed`, *Invite expired* where it holds `Expired`, and *Declined to sign* where it holds `Declined`.

The two objects do not share a vocabulary either. `Pending`, `Signed` and `Declined` appear on both; `Draft` exists only at invite level, and `Expired`, `View Only` and `Invite Step Pending` only at signer level.

Both objects are reportable. See [Custom reports](https://docs.signnow.com/docs/custom-reports).

## Example: update an Opportunity when a recipient signs

Let's build a flow that moves an Opportunity to **Closed Won** when a contract sent from it is signed.

### Step 1. Create a record-triggered flow

In Salesforce Setup, open **Flows** and create a **Record-Triggered Flow**.

- **Object**: `SignNow Signer` (`cuda_signnow__SignNow_Signer__c`)
- **Trigger the Flow When**: A record is updated
- **Condition Requirements**: All Conditions Are Met (AND)
- **Entry condition**: `Status` Equals `Signed`
- **When to Run the Flow for Updated Records**: Only when a record is updated to meet the condition requirements
- **Optimize the Flow for**: Actions and Related Records

The entry condition keeps the flow from running on every signer update, so it runs once per recipient, at the moment that recipient signs.

![flow_signer_trigger.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/flow_signer_trigger.png)

### Step 2. Get the Opportunity

Add a **Get Records** element.

- **Label**: `Get Opportunity`
- **Object**: `Opportunity`
- **Condition Requirements**: All Conditions Are Met (AND)
  - `Id` Equals `$Record > SignNow Invitation > Context ID`
- **How Many Records to Store**: Only the first record
- **How to Store Record Data**: Automatically store all fields

In the resource picker, **SignNow Invitation** appears twice. Use the one under **Relationship Fields** with a `>` chevron, which drills into the parent record. The plain text entry is the raw ID and produces a data type error.

> If invites in your org are sent from more than one object, add a second condition on `$Record > SignNow Invitation > Context Table` Equals `Opportunity`. Without it the flow tries to match a Context ID that may belong to an Account or a custom object, finds nothing, and does nothing, with no error to explain why.

![flow_get_opportunity.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/flow_get_opportunity.png)

### Step 3. Check that a record was found

Add a **Decision** element.

- **Label**: `Opportunity found`
- **Outcome**: `Found`
- **Condition**: `Get_Opportunity` **Is Null** `False`

Easy to skip, worth keeping. If Get Records matches nothing, the flow carries on and the update silently affects no records.

![flow_opportunity_found.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/flow_opportunity_found.png)

### Step 4. Update the Opportunity

On the `Found` path, add an **Update Records** element.

- **Label**: `Update Opportunity`
- **How to Find Records to Update and Set Their Values**: Specify conditions to identify records, and set fields individually
- **Object**: `Opportunity`
- **Condition Requirements**: All Conditions Are Met (AND)
  - `Id` Equals `Get_Opportunity > Opportunity ID`
- **Set Field Values**: `Stage` = `Closed Won`

Click **Save**, then **Activate**.

![flow_update_opportunity.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/flow_update_opportunity.png)

### Step 5. Test it

Send an invite from an Opportunity and sign it. The Opportunity's **Stage History** shows the change.

You can also click **Debug** and run the flow against an existing signer record whose `Status` is `Signed`, selecting **Roll back changes made to records** to leave the Opportunity untouched. The record lookup searches by the auto-number **Name**, not by ID, and a record already at `Signed` is not transitioning into that state, so select **Skip start condition requirements** if the flow does not start.

### Result

Each recipient who signs updates the Opportunity the invite was sent from.

![flow_result_stage_history.png](/reference-assets/images/SignNow_Salesforce/invite_status_tracking/flow_result_stage_history.png)

### Branching by signer

Because the flow runs once per recipient, you can branch on which one signed. Add a formula resource on `$Record.cuda_signnow__Order__c` to set a different value for the first, second and final signer, or test `$Record.cuda_signnow__Email__c` to act only on a particular recipient. A worked example of staged Opportunity updates is on the [SignNow Invite Status Update event](https://docs.signnow.com/docs/apex-invite-status-update-event) page.

## Legacy: cuda_signnow__SignNowStatus__c

`cuda_signnow__SignNowStatus__c` belongs to the previous SignNow for Salesforce app. Do not build new automation on it.

Its role is now split: use `cuda_signnow__SignNow_Event__e` to react to a change as it happens, and `cuda_signnow__SignNow_Invitation__c` and `cuda_signnow__SignNow_Signer__c` to query and report on invite and recipient state.

## Related

- [SignNow Invite Status Update event](https://docs.signnow.com/docs/apex-invite-status-update-event)
- [Apex Actions](https://docs.signnow.com/docs/salesforce-apex-actions)
- [Invites Status widget](https://docs.signnow.com/docs/salesforce-invites-status-widget)
- [Custom reports](https://docs.signnow.com/docs/custom-reports)


---
*Full page: https://docs.signnow.com/docs/salesforce-signing-status-and-record-updates*
