# Call metadata

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

HTML version: https://developer.m-files.com/APIs/gRPC-API/runtime/call-metadata/

Part of the M-Files call contract is not in any message: it travels in gRPC metadata (HTTP/2
headers and trailers). In short: send `mfiles-session-id-bin` (the session ID from `LogIn`),
`mfiles-activity-id-bin` (16 random bytes) and `mfiles-is-remote-call: true` on every call, keep
cookies on M-Files Cloud, and read the error and metadata structure version trailers from the responses.
This page lists every key.

## Binary keys

Keys that end in `-bin` carry bytes. gRPC libraries base64-encode them on the wire and decode them
for you, so pass and read raw bytes:

| Language | Sending `mfiles-session-id-bin` |
|---|---|
| Python | `metadata=[("mfiles-session-id-bin", session_id_bytes)]` |
| Go | `metadata.Pairs("mfiles-session-id-bin", string(sessionID))` |
| C# | `new Metadata { { "mfiles-session-id-bin", sessionIdBytes } }` |

The server reads a key only when it occurs exactly once in the call. A key sent twice counts as
missing.

## Request metadata

| Key | Value | When to send |
|---|---|---|
| `mfiles-session-id-bin` | The 48 bytes of `session_data.session_id` from [LogIn](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCLogin/LogIn/index.md), unchanged | Every call that needs a session. See [Authentication and sessions](https://developer.m-files.com/APIs/gRPC-API/runtime/authentication/index.md). |
| `mfiles-activity-id-bin` | 16 bytes, a new random GUID per call | Recommended on every call. |
| `mfiles-is-remote-call` | `true` | Always. |
| `cookie` | The cookies the server set, `name=value; name2=value2` | Every call, once the server has set any. See below. |
| `x-mf-session-assertion` | A session assertion | Not for third-party callers; see [Authentication](https://developer.m-files.com/APIs/gRPC-API/runtime/authentication/index.md#session-assertions). |

**`mfiles-session-id-bin`.** Missing, unknown or expired: `UNAUTHENTICATED`. A value that is not
48 bytes long is rejected: on a plain endpoint with `UNKNOWN` and `E_INVALIDARG` ("The parameter
is incorrect."), on a TLS endpoint with `UNAUTHENTICATED`. Methods that need no session ignore it.

**`mfiles-activity-id-bin`.** Identifies the call in the server's logs and traces, so support can
find it. The server reads it only from calls that carry a session ID. Optional, but if you send it,
it must be exactly 16 bytes: other lengths fail with `E_INVALIDARG`. M-Files' clients send a new
GUID for every call; log it on your side to correlate.

**`mfiles-is-remote-call`.** Tells the server that the caller is not one of its own local
processes. Send `true` on every call; the server checks only that the key is present.

**Not read.** MFServer reads no other request metadata. In particular, W3C trace context
(`traceparent`) is not used; correlate with `mfiles-activity-id-bin`.

## Response metadata

| Key | Where | Value |
|---|---|---|
| `mfiles-metadata-version-bin` | Trailer, successful calls of methods that report it | The vault's metadata structure version: 4 bytes, little-endian signed 32-bit integer |
| `mfiles-error-text-bin` | Trailer, failed calls | UTF-8 text of the server-side error stack. See [Errors](https://developer.m-files.com/APIs/gRPC-API/runtime/errors/index.md). |
| `mfiles-error-serialized-bin` | Trailer, failed calls | A serialized [RPCErrorInfoArray](https://developer.m-files.com/APIs/gRPC-API/Reference/Messages/MFiles.RPCErrorInfoArray/index.md). See [Errors](https://developer.m-files.com/APIs/gRPC-API/runtime/errors/index.md). |
| `set-cookie` | Header, M-Files Cloud | For example `mfilesmsm=69621a771a22b419; Path=/; Max-Age=172800; Secure; SameSite=None` |

**`mfiles-metadata-version-bin`.** Methods marked `returns_metadata_structure_version` in the reference
(for example [GetObjectTypes](https://developer.m-files.com/APIs/gRPC-API/Reference/MFiles.IRPCObjectTypes/GetObjectTypes/index.md)) return it on success.
The bytes `00 04 00 00` are version 1024. The version changes when the vault's metadata structure
(object types, value list definitions, classes, property definitions and so on) changes; it does
not change when objects or value list items change. A failed call has no such trailer.
[Metadata structure version and caching](https://developer.m-files.com/APIs/gRPC-API/concepts/metadata-structure-version-and-caching/index.md) lists which results
are safe to cache by this version.

An on-premises server sends no response headers of its own; everything else is in trailers.

## Cookies and stickiness

M-Files Cloud puts a front end in front of the server, and a vault can be served by more than one
server instance. The front end sets the cookie `mfilesmsm` on its responses to pin a client to
one instance:

* A new connection without the cookie gets one; different connections can get different values.
* A call that sends a valid `mfilesmsm` back gets no new `set-cookie`.
* An unknown value is replaced with a new cookie.

Keep cookies like a browser: store `set-cookie` values from response headers and send them in a
`cookie` header on every later call of the same session. M-Files' own clients do this for every
call. Multi-step file transfers depend on it, because their upload and download sessions exist only
in the server process that created them (see [Files](https://developer.m-files.com/APIs/gRPC-API/runtime/files/index.md)). The cookie lasts 48 hours
(`Max-Age=172800`).

gRPC libraries do not keep cookies themselves; add an interceptor that reads the response headers
and adds the `cookie` header.

## Deadlines and cancellation

Set a deadline (timeout) on every call; without one, a call to a stalled connection waits forever.

The server does not stop a unary call when its deadline passes or the client cancels it: the call
runs to completion and only its result is lost. Verified: an `AddObjectWithFiles` call with a
5 ms deadline returned `DEADLINE_EXCEEDED` to the client, and the object was created anyway.
Therefore:

* After `DEADLINE_EXCEEDED` or `CANCELLED` on a call that changes data, the outcome is unknown.
  Read the current state before you retry.
* Methods marked `idempotency_level = IDEMPOTENT` in the `.proto` can be retried as they are.

## Call importance

Some request messages have a [CallImportance](https://developer.m-files.com/APIs/gRPC-API/Reference/Enums/MFiles.CallImportance/index.md) field (`callimp` or
`call_importance`). Leave it at `CALL_IMPORTANCE_DEFAULT` or set `CALL_IMPORTANCE_NORMAL`: such
calls are never rejected for load. With `CALL_IMPORTANCE_CAN_BE_REJECTED` the server refuses the
call with `E_MFILES_CALL_REJECTED` ("The server is too busy to process the request at this time.")
while it is serving more requests than its limit (by default the number of logical processors of
the server machine). Use it for background work such as prefetching, and try again later when it
is rejected.
