Exchange API timestamp units must be defined for each field and endpoint: seconds, milliseconds and microseconds are different representations of an instant, while a receive window is a duration with its own unit. Preserve the original value and documented unit, normalize through an explicit conversion, and validate the serialized request. Digit counting is a diagnostic clue, not a reliable decoding contract.
A unit mistake can make a correct clock appear decades wrong, place historical queries outside their intended range or collapse distinct events into one timestamp. The useful question is therefore more specific than “does this exchange use milliseconds?” Ask which API product, transport, field and negotiated mode produced the value.
Define what the field measures before converting it
A timestamp represents an instant relative to an origin, often the Unix epoch. A duration represents an amount of time. An event timestamp, response-generation timestamp and client receipt timestamp may all use milliseconds while describing different observations.
An adapter's time contract should record these properties together:
| Property | Example entry | What it prevents |
|---|---|---|
| Source scope | Venue, product, environment, endpoint or stream | Applying one API family's rule to another |
| Field meaning | Trade execution instant | Substituting response time for event time |
| Origin and unit | Unix epoch, integer microseconds | Treating an epoch count as elapsed process time |
| Wire representation | Decimal digit string | Losing precision during numeric decoding |
| Selected mode | Response microseconds explicitly requested | Forgetting a request header or stream option |
| Conversion policy | Exact microseconds; millisecond view floors | Concealing information discarded for display |
Include the actual host in that scope. The regional endpoint guide explains why a venue name alone does not identify the service being used. Check the time contract again when an integration moves between products or environments.
Keep the unit question separate from clock quality. Converting seconds to milliseconds cannot correct a clock offset. The existing wall-clock and monotonic-clock guide covers choosing a clock for signed epoch values and elapsed request budgets. This article concerns how a value survives the conversion boundaries afterward.
Read the endpoint contract rather than infer an exchange-wide rule
Current official documentation provides useful counterexamples to a universal unit assumption.
Binance Spot REST JSON timestamps default to milliseconds. Adding the documented request header X-MBX-TIME-UNIT: MICROSECOND selects microseconds in JSON responses; timestamp request parameters can be milliseconds or microseconds. See Binance Spot REST time units. Its recvWindow remains expressed in milliseconds, with up to three decimal places, under Binance Spot timing security. A microsecond response mode is therefore not permission to multiply every time-related parameter by 1,000.
Binance Spot WebSocket Streams use a separate URL option, timeUnit=MICROSECOND, to request microsecond timestamps. A REST header setting does not configure that connection. Preserve the selected mode with the stream configuration, including the reconnect path. See Binance Spot stream timestamp units.
Bybit V5's server-time endpoint returns timeSecond and timeNano as strings containing seconds and nanoseconds. Its common response time and authenticated X-BAPI-TIMESTAMP use milliseconds. The units differ even within a related set of requests. See Bybit server-time response fields and Bybit V5 authentication and common response fields.
Coinbase Exchange REST authentication instead defines CB-ACCESS-TIMESTAMP in epoch seconds and allows decimal values. A decimal point can carry subsecond information without changing the field's unit to milliseconds. See Coinbase Exchange timestamp selection.
These are specific documented examples reviewed on 26 October 2026. They do not establish rules for every product offered by those organizations. Record the relevant documentation version or review date alongside the adapter configuration.
Make exact conversion and information loss visible
For the same instant, whole seconds multiply by 1,000 to become milliseconds; milliseconds multiply by 1,000 to become microseconds. Microseconds multiply by another 1,000 to become nanoseconds. These factors are exact. Whether the incoming value has enough information to produce a finer timestamp is a separate question.
Multiplying 1793016000 seconds by one million produces 1793016000000000 microseconds. It does not reveal where within that second the event occurred. Extra trailing zeros provide a different representation, not better measurement resolution.
Going toward a coarser unit may discard information. An integer microsecond timestamp divided by 1,000 has an integer millisecond quotient and a remainder. Preserve that remainder, preserve the original timestamp, or explicitly document why the application can discard it. Do not silently round an ordering key merely because a date display accepts only milliseconds.
Use integer or exact decimal operations appropriate to the schema. Avoid parsing a decimal-second string into binary floating point and later assuming every microsecond survived. Nanosecond epoch counts also need particular care in runtimes with limited integer precision. The large integer preservation guide explains the parsing boundary: converting an already rounded number into a string or larger integer cannot restore its original digits.
Named internal fields such as eventEpochUs and receivedEpochMs make review easier than several generic timestamp fields. A typed wrapper can also carry the unit and semantic role. A sensible internal representation is a design choice; it does not change the wire format an exchange accepts.
A worked fixture: one instant, three representations
Consider an illustrative fixture at 2026-10-26T12:00:00.123456Z. These values are constructed examples, not observed exchange messages.
| Representation | Exact value for the fixture |
|---|---|
| Decimal epoch seconds | 1793016000.123456 |
| Decimal epoch milliseconds | 1793016000123.456 |
| Integer epoch microseconds | 1793016000123456 |
| Integer milliseconds after flooring | 1793016000123 |
| Microsecond remainder discarded by that floor | 456 |
The fractional-millisecond row illustrates arithmetic, not a claim that a particular exchange accepts that wire format. Sending a value still requires the endpoint's allowed type and precision.
Now add an event 250 microseconds later, at 1793016000123706 microseconds. Both events floor to 1793016000123 milliseconds. A database key made only from that millisecond value would collide, despite exact conversion. Keep the documented event identity or sequence where available; a finer timestamp alone is not a uniqueness guarantee either.
A different error occurs if the first microsecond value is labeled milliseconds without dividing. The represented epoch duration becomes 1,000 times larger. A date library might reject the value or produce a remote future date. Either result is a unit failure; adjusting a signing machine's clock cannot fix it.
The fixture also gives a useful reverse check. Reconstructing from floored milliseconds yields 1793016000123000 microseconds, which is 456 microseconds earlier than the original. An exact conversion must round-trip unchanged. An intentionally lossy conversion must satisfy its declared loss bound; for flooring nonnegative integer microseconds to milliseconds, that loss is from zero through 999 microseconds.
Validate the entire path, including stream reconnects
Apply the fixture at the raw decoder, normalized record, database, queue and outgoing serializer. A correct conversion function is insufficient if a database driver converts a stored exact integer into an imprecise runtime number on retrieval.
Use a small acceptance worksheet for each endpoint family:
| Test | Passing evidence |
|---|---|
| Equivalent second and microsecond fixtures | Same normalized instant with retained source units |
| Two events 250 microseconds apart | Both survive storage and deduplication under distinct identities |
| Microsecond input mislabeled as milliseconds | Rejected by the configured contract or plausibility check |
| Coarser output requested | Declared rounding policy and measurable retained or discarded remainder |
| Stream reconnected | Expected time-unit option present and first payload checked |
| Signed request constructed | Final timestamp spelling uses the required unit before signing |
A plausibility check should use the expected interval for that dataset. Historical records can legitimately be old, while a new authentication timestamp should be near current time. Do not repair an out-of-range value by repeatedly dividing until it resembles today's date. Retain the raw value, mark the record unvalidated and investigate the field contract.
Likewise, do not assume ten, thirteen or sixteen digits prove seconds, milliseconds or microseconds. Those lengths can be useful for contemporary integer epoch diagnostics, but decimal seconds, older history and unexpected field meanings undermine the heuristic. Missing unit metadata should produce a visible validation failure rather than a guessed instant.
The field meaning still matters after every unit test passes. In a balance snapshot and delta workflow, an accurately decoded response timestamp does not by itself identify the sequence boundary between a snapshot and subsequent changes. Retain the provider's documented reconciliation evidence with the time data.
For the next adapter review, select one raw response and trace its time fields to storage and back to a serialized request. Write down each unit, conversion and loss policy. The task is complete when every timestamp has an explained origin and every discarded digit has an explicit reason.
