It's the hash of the root of the state trie, whereas receiptRoot is the hash of the array of receipts for a given block.
root
In GetTransactionReceipt() in api.go there's set of mappings, one of which is:
"root": common.Bytes2Hex(receipt.PostState),
Looking at receipt.go, PostState is a byte array:
// Receipt represents the results of a transaction.
type Receipt struct {
// Consensus fields
PostState []byte
CumulativeGasUsed *big.Int
Bloom Bloom
Logs vm.Logs
This is set in NewReceipt() to a value passed in from state_processor.go:
receipt := types.NewReceipt(statedb.IntermediateRoot().Bytes(), usedGas)
...and IntermediateRoot() is defined in statedb.go as:
// IntermediateRoot computes the current root hash of the state trie.
// It is called in between transactions to get the root hash that
// goes into transaction receipts.
receiptRoot
In block.go:
// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
// are ignored and set to values derived from the given txs, uncles
// and receipts.
With the pertinent code in that function being:
b.header.ReceiptHash = DeriveSha(Receipts(receipts))
And in api.go:
"receiptRoot": b.ReceiptHash(),