Not verified hands-on. This article was written from primary documentation rather than reproduced in an org, so it carries no tested-release badge. If you run it and something differs, say so in the comments and it gets tested and corrected.

The standard Contract object is a record of an agreement with an account, a date range, a status lifecycle and a signature trail. It has no line items, no versioning, no amendments and no renewal logic. It is a filing cabinet, and the moment your business needs a contract to know what was sold, you are building something on top of it or replacing it.

The fields that carry the model

Contract hangs off Account. The ones that matter:

  • ContractNumber, auto number, not yours to format.
  • StartDate and ContractTerm, a whole number of months.
  • EndDate, which is read-only and derived from those two. You cannot set it directly, which surprises every integration written against it.
  • Status, plus a system StatusCode underneath.
  • CustomerSignedId, CustomerSignedTitle, CustomerSignedDate and the company-side equivalents.
  • OwnerExpirationNotice, which sends the owner a reminder a set number of days before the end date.

The derived end date is the first thing that pushes people to custom fields. A contract running to a specific date that is not a whole number of months from the start cannot be represented accurately, so orgs add Contract_End__c and stop using the standard field. Do that early or do not do it at all, because two end dates in one org is a reporting problem forever.

The status lifecycle

Contract statuses are records in the ContractStatus setup object, and each one maps to a status category: Draft, In Approval Process, or Activated. You can add your own labels (Pending Signature, Awaiting Countersignature), but each must sit in one of those three categories, and the category is what the platform reacts to.

Activation is the meaningful transition. Moving a contract to a status in the Activated category stamps ActivatedById and ActivatedDate, and locks the record. After that, editing requires the Edit Activated Contracts permission, which is not in most profiles by default.

That lock is the object’s one genuinely useful behaviour. It gives you a record that a named person marked as live at a known moment and that ordinary users cannot quietly change afterwards. If you are going to use standard Contracts, use that.

SELECT Id, ContractNumber, AccountId, Status, StatusCode,
       StartDate, ContractTerm, EndDate, ActivatedDate, ActivatedById
FROM Contract
WHERE StatusCode = 'Activated'
AND EndDate = NEXT_N_DAYS:90

That query is the renewals list. There is no standard view that produces it, which tells you how much renewal thinking went into the object.

What it does not do

Be clear about the gaps before anyone promises a feature on top of them:

  • No line items. Contract has no products. ContractLineItem belongs to ServiceContract in the entitlements model, which is a different object for a different purpose.
  • No amendments or versions. Changing a contract changes the contract. There is no history of what version three said, beyond field history tracking.
  • No renewal. Nothing creates a successor record. The expiration notice emails the owner and stops there.
  • No link to the opportunity. There is no standard lookup from Contract to Opportunity. Orders link to contracts, opportunities do not.
  • No document. The signed PDF is a file you attach. Salesforce is not storing your paper.

When to build your own

Stay on the standard object when contracts are a reference record: you want to know which accounts have a live agreement, when it ends, and who signed it. That is most professional services and most straightforward B2B.

Build a custom object when any of these are true. Contracts need line-level detail that drives billing. Amendments happen mid-term and both the original and the change must be readable afterwards. One agreement covers several accounts. Renewal is a process with its own stages and owner rather than a date.

The middle path that works is a custom object for the commercial detail with a lookup to the standard Contract, keeping activation and the signature trail where they are. It is more objects than you wanted and it avoids rebuilding the locking behaviour badly.

What does not work is stretching the standard object with twenty custom fields and a flow that clones it at renewal. That gets you a half-built contract system with none of the guarantees of either option.

Frequently asked

Can I un-activate a contract? Only with the Edit Activated Contracts permission, and the activation stamps stay as they were. Treat activation as one-way for ordinary users.

Why will the end date not save? It is calculated. Set ContractTerm instead, in whole months.

Do contracts have sharing? Yes, Contract has its own org-wide default and a share object. It is not controlled by the parent Account.

Is there an approval step built in? No, the In Approval Process status category is just a category. Wire it to a real approval process yourself.