> This page is for SDK, version Legacy.
> For other versions, use one of these documentation indexes:
> - Current (default): https://buildwithfern.com/learn/sdks/current/llms.txt
> - Legacy: https://buildwithfern.com/learn/sdks/legacy/llms.txt

> For clean Markdown content of this page, append .md to this URL. For the complete documentation index, see https://buildwithfern.com/learn/llms.txt. For task-scoped instructions for coding agents working in a Fern project, see https://buildwithfern.com/learn/home/fern-instructions.md.

## 1.39.8

**`(fix):`** Response parsing is faster on large payloads. `Model#initialize` no longer coerces fields whose value is nil or
copies its input hash twice, `Utils.coerce` returns exact `String`, `Integer`, and `Float` instances without
walking the full type match, and type dispatch in `Utils.coerce` and
`Model.===` no longer allocates a lambda or ancestor list per call. Parsed output is unchanged.

## 1.39.7

**`(fix):`** The gem's root file registers generated types with `autoload` instead of requiring every type
file eagerly, so `require "<gem>"` only loads the runtime and each type is read on first use.
Type files also `require_relative` the root file, so a single type can be required directly
(e.g. `require "<gem>/twiml_voice/types/voice_response"`) without a NameError.

## 1.39.6

**`(fix):`** `Time` and `ActiveSupport::TimeWithZone` values are now sent as RFC 3339 strings
with millisecond precision (e.g. `"2026-10-16T01:40:16.000Z"`) in JSON request
bodies, query parameters, form-urlencoded bodies, and multipart form fields.
Previously they were sent via `Time#to_s` (e.g. `"2026-10-16 01:40:16 UTC"`),
which is not RFC 3339. `Date` and `DateTime` values are unchanged. Set
`serializeTimeAsIso8601: false` in the generator config to keep the previous output.

## 1.39.5

**`(fix):`** Ruby dynamic snippets now use wire names for keys inside nested hashes (e.g. `httpEndpoint:` instead of `http_endpoint:`), pass file upload fields (example file contents as `StringIO.new(...)`, since the SDK reads a String as a file path; a missing required file gets a `"/path/to/your/file"` path placeholder, and a missing optional file is left out; dynamic IR from CLIs that predate the `isOptional` flag treats every file as required), and show an undiscriminated union body whose example isn't an object as the keyword arguments of its first object variant instead of `request:` with an error.

**`(fix):`** `Model#to_h` now serializes models nested as map values, so a map of objects is sent as JSON objects instead of Ruby inspect strings.

**`(fix):`** Multipart uploads of a readable object with no path or name (e.g. `StringIO`) now send the form field name as the part's `filename`. Before, the part had no `filename`, so servers that tell files from text fields by `filename` read it as a text field. With a filename set, the part also gets the default `Content-Type: application/octet-stream` unless `content_type:` is passed, the same as `File` uploads. Elements of a file list each get the field name as their filename.