# Objects and versions

Location: [gRPC API](https://developer.m-files.com/APIs/gRPC-API/index.md) > [Concepts](https://developer.m-files.com/APIs/gRPC-API/index.md#concepts)

HTML version: https://developer.m-files.com/APIs/gRPC-API/concepts/objects-and-versions/

Everything stored in a vault is an **object** of some object type: a document, a customer, a
project. Changes are made in new **versions** of the object; older versions stay readable, and
most read calls ask for one specific version.

## Identity: ObjID and ObjVer

```text
ObjID   type: 0                                   object type (0 = Document)
        item_id { internal_id: 358 }              object ID within that type
ObjVer  obj_id { type: 0 item_id { internal_id: 358 } }
        version { type: OBJ_VER_VERSION_TYPE_SPECIFIC internal_version: 3 }
```

- [ObjID](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjID/index.md): `type` is the object type ID and `item_id.internal_id` the
  object's ID. IDs are unique only within an object type: document 142 and customer 142 are
  different objects. Never pass an object ID without its type.
- [ObjVer](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjVer/index.md): an `ObjID` plus an [ObjVerVersion](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjVerVersion/index.md).
  Version numbers grow with each change.
- [ObjectVersionEx](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjectVersionEx/index.md) is what reads and searches return: version
  information in `version_info` ([ObjectVersion](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjectVersion/index.md): version, title,
  class, files) and object-level information in `object_info`
  ([ObjectLevelInfo](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.ObjectLevelInfo/index.md): ID, GUID, check-out state, flags).

## Latest or specific version

`ObjVerVersion.type` says what `internal_version` means. Versions returned by the server are
always `OBJ_VER_VERSION_TYPE_SPECIFIC` with a number. Requests should send the same:

- [GetProperties](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetProperties/index.md) and
  [GetObjectFiles](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectFiles/index.md) need a specific version.
  `OBJ_VER_VERSION_TYPE_LATEST` (which the server reads as version -1), `OBJ_VER_VERSION_TYPE_ANY`
  and an unset version all fail with "Not found."
- To read the latest version, use a method with its own "latest" switch:
  [GetObjectInfoAndProperties](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectInfoAndProperties/index.md)
  (`latest_version`),
  [GetObjectVersionAndPropertiesOfMultipleObjects](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectVersionAndPropertiesOfMultipleObjects/index.md)
  (`latest_versions`), [GetObjectInfo](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectInfo/index.md)
  (`latest_version`); or get the number first with
  [GetLatestObjectVersion](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetLatestObjectVersion/index.md).
- Lookup values are the exception: a lookup to an object normally refers to its latest version,
  and the server returns such lookups with `OBJ_VER_VERSION_TYPE_LATEST` and -1.

"Latest" means the latest checked-in version, except for the user who has the object checked
out: with `allow_checked_out` true (and in `GetObjectInfo`), that user gets the checked-out
version.

## Check-out and check-in

An object is changed through a **checked-out version**: a new version that only the user who
checked it out can see and edit until it is checked in.

```text
AddObject(check_in: false)   v1 checked out to you        others: "Not found."
CheckIn(v1)                  v1 checked in                everyone with access sees v1
CheckOut                     v2 checked out to you        others still see v1
SetProperties(v2), ...       still v2                     edits do not add versions
CheckIn(v2)                  v2 checked in                (or UndoCheckout(v2): v2 is discarded)
SetProperties(v2, allow_modifying_checked_in_object: true)
                             v3 checked in in one call    check-out, change, check-in
```

The sequence above was run against the Sample Vault. Points to remember:

- [CheckOut](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/CheckOut/index.md) takes an `ObjID` and returns the new
  version; `previous_version` is the version it was made from.
  `ObjectLevelInfo.checked_out_version` and `checked_out_to_user_id` show the check-out state;
  `checked_out_version` is 0 when the object is not checked out.
- While a user has the object checked out, other users cannot change it: `CheckOut` and
  `SetProperties` fail with "The object is checked out to another user." They cannot read the
  checked-out version either.
- [SetProperties](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/SetProperties/index.md) on a checked-in version
  fails with "The object is not checked out." unless `allow_modifying_checked_in_object` is
  true. Add `fail_if_newer_version_exists` to make the call fail ("There is a newer version of
  this object on the server.") when someone else has changed the object since you read it.
- [UndoCheckout](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/UndoCheckout/index.md) discards the checked-out
  version.
- An object created with `check_in` false is visible only to its creator until it is checked
  in, and `GetLatestObjectVersion` with `allow_checked_out` false answers "No checked-in
  version available."
- Give a new object an ACL when you create it: without one it gets an empty ACL and, once
  checked in, only users with the vault-level right to see all objects can read it, not even
  its creator. See [Permissions](https://developer.m-files.com/APIs/gRPC-API/concepts/permissions/index.md#give-new-objects-an-acl).

## Files: single-file and multi-file documents

Files belong to object versions; there is no file without an object. Object types whose
`OBJTYPEFLAGS.can_have_files` is true (documents, for example) can carry files, and their objects
must have property 22 (Single file):

- **Single-file document** (`Single file` true, `ObjectVersion.is_single_file_object` true):
  exactly one file.
- **Multi-file document** (`Single file` false): any number of files, including none.

Creating a document without property 22 fails with 'The mandatory property value "Single file"
is missing.' Each [File](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.File/index.md) in `ObjectVersion.files` has a
[FileVer](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.FileVer/index.md): a file ID and a file version. Files have versions of their
own, separate from the object's version numbers. How to download and upload file content is
described in [Files](https://developer.m-files.com/APIs/gRPC-API/runtime/files/index.md).

## Deleted and destroyed

| | Deleted ([RemoveObject](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/RemoveObject/index.md)) | Destroyed ([DestroyObject](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/DestroyObject/index.md)) |
| --- | --- | --- |
| Data | kept; `ITEMFLAGS.is_deleted` set | removed permanently |
| Normal users | "Not found."; not in search results | "Not found." |
| Users with `see_deleted_objects` | visible; found by searches without a "not deleted" condition | "Not found." |
| Way back | [UndeleteObject](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/UndeleteObject/index.md) | none |

Undeleting and destroying need the vault-level rights `undelete_objects` and `destroy_objects`
(see [Permissions](https://developer.m-files.com/APIs/gRPC-API/concepts/permissions/index.md)), and seeing deleted objects needs `see_deleted_objects`. In
the Sample Vault a normal user could delete an object but got "Access denied. You do not have the
access rights required by this operation." for undelete and destroy; a vault administrator could
do both. `DestroyObject` takes `all_versions` true with version type
`OBJ_VER_VERSION_TYPE_ALL`, or a single version.

## GUIDs and external IDs

- **Object GUID**: `ObjectLevelInfo.guid`, or
  [GetObjectGUID](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjectGUID/index.md).
  [GetObjIDByGUID](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectOperations/GetObjIDByGUID/index.md) maps it back to an `ObjID`.
  Each version also has its own GUID (`ObjectVersion.version_guid`).
- **External ID**: `ObjectLevelInfo.external_id` and `external_id_status`
  ([ExtIDStatus](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.ExtIDStatus/index.md)) link an object to a record in an external database.
  For objects created in the vault the status is `EXT_IDSTATUS_INTERNAL`. The
  `STATUS_TYPE_EXTERNAL_ID` search condition finds objects by external ID.

Store the `ObjID` (or the GUID) of an object, not its title or a version number: titles change,
and every edit makes a new version.
