sgcOpenAPI release notes

Every public release of sgcOpenAPI, newest first. Each version lists what was added, what was fixed and anything that changes behaviour, exactly as it is written in the history file that ships with the product.

sgcOpenAPI product page · Download

sgcOpenAPI 2026.9.0 Latest

  • 2026.9.0: 2026 September
  • NewThe OpenAPI Parser now reads a specification that is not valid UTF-8. A JSON document must be UTF-8 according to RFC 8259, so the file is read as Windows-1252 and a warning is recorded instead of the parse failing. A UTF-16 file with a byte order mark is also read correctly.
  • NewThe OpenAPI Parser now records warnings instead of failing silently. A missing openapi or info member, a member with the wrong JSON type, an operation that could not be generated, an unresolved path item reference and a JSON Schema keyword that is parsed but not yet honoured are all reported through the new Warnings property.
  • NewThe OpenAPI Parser now understands which version of the specification it is reading, so a 3.0 document and a 3.1 document are no longer treated as the same thing. exclusiveMinimum and exclusiveMaximum are read as booleans in 3.0 and as numbers in 3.1, which is what each version requires.
  • NewImproved OpenAPI Parser: added support for the OpenAPI 3.1 webhooks, jsonSchemaDialect and components.pathItems members, the license identifier, the mutualTLS security scheme, a type declared as an array such as ["string","null"], and a schema declared as a boolean. The remaining JSON Schema 2020-12 keywords are read and reported as not yet honoured rather than being dropped without trace.
  • NewImproved OpenAPI Parser: added support for the OpenAPI 3.2 query operation and the additionalOperations map, so a path that declares them now generates the matching methods. They travel as a POST with an X-HTTP-Method-Override header.
  • NewImproved OpenAPI Parser: an inline object schema now generates its own class instead of degrading to a string, and items is now read as a complete schema, so an array of inline objects, an array of enums and a nested array all generate the right type.
  • NewImproved OpenAPI Parser: the generated client now supports cookie parameters, and the full OpenAPI parameter serialization rules, matrix, label, simple, form, spaceDelimited, pipeDelimited and deepObject, with explode and allowReserved.
  • NewNew OpenAPI command line switch -r (or -remote) to allow converting a YAML or Swagger 2.0 document through the public converter at converter.swagger.io. It is off by default, see the breaking changes below.
  • NewThe OpenAPI command line now sets an exit code, 0 on success and 1 to 7 for the different failures, so a build script can tell whether it worked. Error messages are now always written to the standard error output; the -l switch is only for progress logging.
  • FixedFixed Bug OpenAPI Parser: the generated unit did not compile when a schema property was named after a Delphi reserved word such as property, class, string or function, when two properties differed only in case such as Name and name, or when a reference used a JSON Pointer escape such as #/components/schemas/Foo~1Bar. The wire name is preserved with a JSONName attribute when a property has to be renamed.
  • FixedFixed Bug OpenAPI Parser: parameters declared once at the path level, which is the style the specification recommends and the style most public specifications use, were parsed and then dropped. The generated method took no arguments and the request was sent with the literal placeholder still in the URL, for example /pets/{petId}.
  • FixedFixed Bug OpenAPI Parser: a specification containing any character outside ASCII was rejected with a UTF-8 error when the file had a byte order mark, and characters such as Chinese or Japanese were silently replaced by question marks.
  • FixedFixed Bug OpenAPI Parser: converting a Swagger 2.0 document turned every number into a string, so a numeric default produced a generated unit that did not compile, and the converted document was not valid OpenAPI 3.0. A Swagger 2.0 discriminator, which is a string, aborted the whole parse with an invalid typecast.
  • FixedFixed Bug OpenAPI Parser: a member with an unexpected JSON type, for example "properties": [] or "servers": ["https://api"], aborted the parse with an invalid typecast instead of being skipped.
  • FixedFixed Bug OpenAPI Parser: a schema of type integer with no default was given a default of 0, and a single valued enum was treated as a const, which removed the parameter from the generated method altogether.
  • FixedFixed Bug OpenAPI Parser: the default response and the ranged responses 2XX, 4XX and 5XX were silently dropped, so an API that declares its errors only with default generated a client with no typed error at all. When several successful responses are declared the lowest one is now used, and application/json is preferred when several media types are declared.
  • FixedFixed Bug OpenAPI Parser: allOf kept only the last of several base schemas and discarded the members of the others, oneOf merged every branch into one class and produced duplicate fields, anyOf was not handled at all and resolved to a string, and a schema declaring both properties and additionalProperties lost all its properties.
  • FixedFixed Bug OpenAPI Parser: the generated enum tables contained the sanitized identifier instead of the value the server expects, so for example allow-all was written as allowall and json-file as jsonfile. The declaration order of the specification is now kept, integer enums also get a table, and an extra Unknown member is generated so a value added later by the server does not silently become the first member.
  • FixedFixed Bug OpenAPI Parser: an external reference with a JSON Pointer fragment such as ./common.yaml#/components/schemas/Error could not be resolved, two files referencing each other crashed the parser, a relative reference inside a sub document was resolved against the root document instead of its own, two external files with the same name silently overwrote each other and could replace a schema of the main document, and a chain of references was only followed one step.
  • FixedFixed Bug OpenAPI Parser: bundling a specification overwrote the input file with no backup and no message, and deleted every typographic apostrophe from the whole document.
  • FixedFixed Bug OpenAPI Parser: an external reference could read any file on the machine, for example ../../../credentials.json, and the contents were copied into the generated unit. External references are now confined to the directory of the main document, with a new option to allow more when it is really needed.
  • FixedFixed Bug OpenAPI Parser: a specification stored in a path containing a space, for example C:\My Specs\, could not resolve its external references.
  • FixedFixed Bug OpenAPI command line: the documented -output switch wrote the generated unit to a file called "utput" in the current directory, and because every message was suppressed the run looked successful. The -x switch also matched other switches beginning with x, such as -xml.
  • FixedFixed Bug OpenAPI command line: nothing at all happened when the tool ran with no console attached, for example from a scheduled task or a build agent, and an existing output redirection was discarded.
  • FixedFixed Bug OpenAPI command line: -h printed a licence error instead of the usage text on a machine that was not activated, an invalid value for -m or -a was accepted silently, and an unknown switch was ignored.
  • FixedFixed Bug OpenAPI Parser: the generated unit was named after the input file instead of the output file, so generating MyClient.pas from petstore.json produced a unit called petstore that did not compile.
  • FixedFixed Bug OpenAPI Parser: info.contact and info.license were never read because of a test that could never be true.
  • FixedFixed Bug OpenAPI Parser: a server URL with several variables substituted the wrong value, and could raise a list index error.
  • FixedFixed Bug OpenAPI Parser: reading the same document twice duplicated every path, tag, server and schema.
  • FixedFixed Bug OpenAPI Parser: a specification extension such as x-tagGroups placed among the paths or the responses was read as if it were a path or a response.
  • FixedFixed Bug OpenAPI Parser: enum, required and tags were parsed with a comma separated text helper, so a value containing a JSON escape or a comma was split or corrupted.
  • FixedFixed Bug OpenAPI Parser: a security requirement listing several schemes kept only the first one, so the requirement that all of them are satisfied was lost.
  • FixedFixed Bug OpenAPI Parser: a response whose schema referenced a top level array component generated a call that did not compile.
  • FixedFixed Bug OpenAPI Parser: the generated file is now written with an explicit encoding, and a character that cannot be represented is reported instead of being silently replaced by a question mark.
  • BreakingOpenAPI Client: the generated clients now verify the certificate of the server they connect to. They did not before, which means they accepted any certificate, including one presented by a man in the middle. To connect to a self signed or test endpoint set TLSOptions.VerifyCertificate to False. Note the certificates are trusted through the OpenSSL default paths, so a machine with no certificate store configured needs TLSOptions.RootCertFile.
  • BreakingOpenAPI Client: the request body is now encoded as UTF-8 by default, as required by RFC 8259, and a class now serializes an empty string as "field": "". Set JSONIgnoreEmptyStrings to True for the previous output. Null values are controlled separately with JSONIgnoreNullValues.
  • BreakingOpenAPI Client: a response no longer frees a ResponseStream supplied by the caller. Set OwnsResponseStream to True for the previous behaviour. Freeing the client from inside its own OnResponse, OnError or OnCancel handler now raises a clear error instead of hanging.
  • BreakingOpenAPI command line: a switch value must now be written as -name value or -name:value. The appended form without a separator, such as -x"GET /pets", is no longer accepted.
  • BreakingOpenAPI Parser: a parameter declared as an array is now generated as an array instead of a string, so the signature of the generated method changes for those operations.

sgcOpenAPI 2026.8.0

  • 2026.8.0: 2026 August
  • NewUpdated the zlib library from 1.2.12 to 1.3.1, which corrects CVE-2022-37434, a heap over-read in inflate that was present in 1.2.12.
  • NewThe Code-First OpenAPI server can now invoke your annotated methods directly. Create a TsgcOpenAPICodeFirstDispatcher, register your service instance with RegisterController and assign it to the new Dispatcher property of the OpenAPI server. Each operation is routed to the method that produced it, the parameters are bound from the path, the query string, the headers or the body following the sgcFromPath, sgcFromQuery, sgcFromHeader and sgcFromBody attributes, and a function result is serialized to JSON and sent with the status code declared in sgcResponse. A method that also takes a TsgcOpenAPIServerContext parameter receives the request context and writes the response itself, so it can answer 201, 204 or 404 as needed. Operations without a controller method still reach the OnRequest event as before.
  • NewThe OpenAPI Parser can now leave endpoints out of the generated code, which is useful with large specifications where only a few endpoints are needed. In the wizard, untick the methods you do not want on the list of parsed methods. From the command line, use -x (or -exclude) with a comma separated list of "VERB endpoint" entries, for example -x "GET /pets,DELETE /pets/{petId}", or pass the name of a file with one entry per line. The same list can be set with the exclude key of the configuration file loaded with -c, and the command line replaces the list read from the file.
  • NewThe OpenAPI Parser can now generate only the classes that the selected endpoints use. Leaving endpoints out did not make the generated file much smaller, because a class was created for every schema of the specification even when no selected endpoint used it. On a specification with 310 endpoints and 1096 schemas, keeping only the 5 authentication endpoints produced a file of 2 MB, and now produces one of 36 KB. In the wizard, tick "Remove Unused Classes" on the parser options page. From the command line, use -p (or -prune), which can also be set with the prune key of the configuration file loaded with -c. The command line option also removes the classes that no endpoint of the specification uses, even when all the endpoints are generated.
  • FixedFixed Bug Code-First: the route declared at class level was applied twice, once as the server url and again on every path, so a service routed /api/v1 with a method routed /tasks was published at /api/v1/api/v1/tasks. The paths of the generated specification are now relative to the server url, so the service is published at /api/v1/tasks. Clients that were calling the duplicated path must be updated.
  • FixedFixed Bug the OpenAPI server answered a request with the first route whose shape fitted it, so a literal path could be handled by a templated route registered before it, for example /tasks/stats answered by /tasks/{taskId}. A literal segment now wins over a parameter segment at the same position.
  • FixedFixed Bug Code-First: two methods routed to the same verb and path were accepted silently, which produced a specification with the same method repeated inside one path and left one of the two methods unreachable. The specification generator and RegisterController now both raise an error naming the verb, the path and the two methods involved. The same path served with different verbs, for example GET and POST on /tasks, remains valid and keeps working.
  • FixedFixed Bug Code-First: enum parameters only accepted their ordinal value, so a request that sent the member name, which is what the generated specification advertises, silently bound the first member. Enum parameters now bind by name first, ignoring case, and fall back to the ordinal. A value outside the range of the enum no longer produces an invalid value, it binds the lowest member of the enum instead.
  • FixedFixed Bug unit sgcHTTPServer_OpenAPI was not deployed in the setup.
  • FixedFixed Bug OpenAPI Parser: when an operation declared error responses but its successful response had no content, for example a DELETE that answers 204 and 404, the generated method created the response object but did not pass it to the request. The client raised an exception instead of returning the error, and the caller was left with an unassigned response. The generated code now passes the response object, so the error is returned and is available in the ErrorNNN property, for example Error404.
  • FixedFixed Bug OpenAPI Client: a response that returned an array leaked one object per item, because the array class never released the objects it read. Those objects are now freed when the response is destroyed, and reading twice into the same array no longer leaks either. Fixed too an access violation raised when the payload of an array response was not a JSON array.
  • FixedFixed Bug OpenSSL: when a TLS connection failed, the real OpenSSL error was discarded and the exception showed a misleading text, for example "error:00000006:lib(0):func(0):EVP lib". Now the exception shows the error reported by OpenSSL.
  • FixedFixed Bug OpenSSL: when the certificate file contained the certificate and the private key together, an error was left pending inside OpenSSL and could affect later calls. Real errors while reading the certificate chain were ignored too. Both cases are now handled properly.
  • FixedFixed Bug OpenSSL: the SSL options (disable old TLS versions, disable compression, disable renegotiation and server cipher preference) were ignored when using OpenSSL 1.1 or later. Now they are applied.
  • FixedFixed Bug OpenSSL: enabling the legacy provider did nothing when legacy.dll could not be found. The failure was silent and showed up later as a confusing certificate error. Now it reports which provider could not be loaded and where it was searched.
  • FixedFixed Bug OpenSSL: improved the error when a PKCS#12 certificate (.p12 or .pfx) cannot be read because it uses an old algorithm such as RC2 40-bit. OpenSSL 3 moved those algorithms to the legacy provider, and the message now explains how to enable it.
  • FixedFixed Bug OpenSSL: the error reported when a PKCS#12 private key fails to load named the certificate function instead of the private key function.
  • FixedFixed Bug OpenAPI Server: when EnforceSecurity was enabled and the matching validation event was not assigned, the security scheme passed instead of failing, so any request that merely carried an api key or an Authorization header reached the operation. A Basic header whose contents could not be decoded, or which had no user and no password, was accepted too, and a scope declared in the specification was not checked when no JWTSecret was configured. The schemes now fail closed. If you enabled EnforceSecurity without assigning OnValidateAPIKey, OnValidateBasic or OnValidateBearer, those requests now answer 401, so assign the event for the schemes your specification declares, or configure JWTSecret.
  • FixedFixed Bug OpenSSL: a TLS connection could write past the end of its read buffer when the other side sent several encrypted records together in the same packet, which could crash the application or corrupt memory next to the buffer. The buffer was told it had more free space than it really had.
  • FixedFixed Bug HTTP Client: the limit on the number of response headers was never applied, so a server could send an endless stream of headers until the client ran out of memory. Setting MaxHeaderLines to 0, which is documented as no limit, had the opposite effect and discarded every response header, including Content-Length and Location.
  • FixedFixed Bug HTTP Client: an NTLM authentication reply shorter than expected was read past its end, so the challenge used to answer it could be taken from unrelated memory and the client could crash. The reply is now checked before it is used, including its signature and its message type.
  • FixedFixed Bug SOCKS Proxy: a UDP reply bigger than the buffer of the caller was copied past the end of that buffer, and a reply that was truncated or declared an unknown address type was read past its end. Replies are now validated and the copy is limited to the size of the buffer.
  • FixedFixed Bug TLS Options: copying the TLS options from one component to another lost most of them. Only the IO handler, the ALPN protocols and the OpenSSL options were copied, so the certificate files, the password, the root certificate, the TLS version, the verify depth, the SChannel options and VerifyCertificate were left at their empty values, and a component set up this way did not verify the certificate of the server it connected to.
  • FixedFixed Bug SOCKS Proxy: several problems when the address is a host name instead of an IP address. The reply from the proxy was read one byte short, so the first byte of the answer reached the application as if it were data, and the port was taken from the wrong position. In the reply to a UDP request, an IPv6 address had two of its bytes read as the port. A host name longer than 248 characters also wrote past the end of the buffer used to build the request.
  • FixedFixed Bug HTTP Client: NTLM authentication now reports clearly that it cannot run, instead of sending an empty answer that no server can accept. The routines that calculate the NTLM response are not available unless SGC_NATIVE_CRYPTO is enabled in the project, and until now the client sent an empty response and the server answered 401 again, which looked like a wrong user name or password. On Windows nothing changes, NTLM is handled by the operating system through SSPI.
  • FixedFixed Bug OpenAPI Parser: the Import column on the list of parsed methods could not be ticked, so every endpoint of the specification was always generated. The column is editable now, and only the methods left ticked are written to the generated unit. The list also shows the endpoint of each method and adds a box to filter it by method name or endpoint, buttons to select all, select none or invert the selection, and a counter of how many methods are selected. The selection is kept when moving back and forward through the wizard, and it is cleared when a different specification is loaded.

sgcOpenAPI 2026.7.0

  • 2026.7.0: 2026 July
  • NewNew OpenAPI Server can now check incoming requests against your API specification (the JSON body plus path and query parameters). Turn it on with the Validation option; a request that doesn't match gets an HTTP 400 and raises an OnValidationError event.
  • NewNew OpenAPI Server can now enforce the security schemes declared in your spec (API Key, HTTP Basic, Bearer/JWT and OAuth2). Turn it on with the EnforceSecurity option; new events (OnValidateAPIKey, OnValidateBasic, OnValidateBearer) let you approve each credential.
  • NewNew OpenAPI Server can serve the Swagger UI from local files instead of the internet, for offline setups (SwaggerUIAssetsPath option).
  • NewNew OpenAPI Server Mock mode returns the example responses from your specification, so you can stand up a stand-in API before the real one is built (Mock option).
  • NewNew OpenAPI Client can now make requests asynchronously and cancel them, with new async request and cancel methods and OnResponse, OnError and OnCancel events.
  • NewNew OpenAPI Parser now accepts older Swagger / OpenAPI 2.0 documents and converts them to OpenAPI 3.0 automatically.
  • NewNew OpenAPI Parser can generate server code from your specification (contract-first). Use the -server command line option (or the GenerateServer property) to create a ready-to-fill service skeleton.
  • NewNew OpenAPI CLI -config option to load all settings from a single JSON configuration file.

sgcOpenAPI 2026.6.0

  • 2026.6.0: 2026 June
  • NewNew OpenAPI Server: TsgcHTTPServer_OpenAPI is a new self-contained component that hosts an OpenAPI 3.0 server with an embedded HTTP server (Indy-based).
  • NewNew Demos: 30.Server/01.CodeFirst and 30.Server/02.SpecFirst updated to use the new standalone TsgcHTTPServer_OpenAPI component.

sgcOpenAPI 2026.5.0

  • 2026.5.0: 2026 May
  • FixedMinor bugs and fixes.

sgcOpenAPI 2026.4.0

  • 2026.4.0: 2026 April
  • NewImproved OpenAPI Parser: added support for cookie parameter location per OpenAPI 3.0 spec.
  • NewImproved OpenAPI Parser: added support for number response type.
  • NewImproved OpenAPI Parser: root-level security requirements are now parsed.
  • NewImproved OpenAPI Parser: root-level tags are now parsed with name, description, and externalDocs.
  • NewImproved OpenAPI Parser: root-level externalDocs is now parsed.
  • NewImproved OpenAPI Parser: Info object now supports the summary field (OpenAPI 3.1.0).
  • FixedFixed Bug OpenAPI Parser: Callbacks in Operation object were reading from wrong JSON key ('responses' instead of 'callbacks').
  • FixedFixed Bug OpenAPI Parser: Operation servers were parsed as singular object instead of array per OpenAPI 3.0 spec.
  • FixedFixed Bug OpenAPI Parser: Double free of schema Items in TsgcOpenAPI_Object_Schema destructor could cause access violations.
  • FixedFixed Bug OpenAPI Parser: OAuth2 Flow properties (authorizationUrl, tokenUrl, refreshUrl, scopes) were not parsed from JSON.
  • FixedFixed Bug OpenAPI Parser: OAuth2 Flow Scopes parsing failed when scope values were strings (tried to cast as JSON objects).
  • FixedFixed Bug OpenAPI Parser: Response and Component headers were not properly parsed from JSON object maps.
  • FixedFixed Bug OpenAPI Parser: Encoding headers in Media Type were read as wrong JSON type (array instead of object).
  • FixedFixed Bug OpenAPI Parser: Link requestBody field crashed when value was a JSON object instead of string expression.
  • FixedFixed Bug OpenAPI Parser: Link parameters were incorrectly read as JSON array instead of object map.

sgcOpenAPI 2026.3.0

  • 2026.3.0: 2026 March
  • FixedMinor bugs and fixes.

sgcOpenAPI 2026.2.0

  • 2026.2.0: 2026 February
  • NewImproved OpenAPI Parser: now allows to convert openAPI files to pascal using the command line.
  • NewImproved OpenAPI Parser: now the executable is compiled for Win32 and Win64. There is a new folder "bin64" for the 64bits version.
  • NewNew OpenAPI library: sgcOpenAPI.dll allows to call the openAPI parser from a dll.
  • NewNew OpenAPI API: when creating the pascal interface file, now you can modify the content of it using a custom sgcOpenAPI_API.dll
  • NewNew Demo for OpenAPI API: in the folder "Demos\sgcOpenAPI_api" there is a delphi demo of the sgcOpenAPI API.
  • FixedFixed some minor setup bugs.

sgcOpenAPI 2026.1.0

  • 2026.1.0: 2026 January
  • FixedFixed Bug OpenAPI: added some missing units.
  • FixedMinor bugs and fixes.

sgcOpenAPI 2025.10.0

  • NewImproved Setup: now the uninstaller is digitally signed.

sgcOpenAPI 2025.9.0

  • NewUpdated sgcIndy to the latest version.
  • FixedFixed Bug sgcIndy: the cipherlist is now set before loading the certificates to allow to set for example the security level. (Thanks to Preben for the fix)
  • FixedFixed Bug OpenAPI Parser: optional Boolean parameters can't send a False parameter in the querystring, now the boolean has been replaced by TsgcOpenAPIBoolean.
  • BreakingOpenAPI: Optional Boolean Parameters have been replace by the enum TsgcOpenAPIBoolean = (oapiBoolNull, oapiBoolFalse, oapiBoolTrue).

sgcOpenAPI 2025.8.0

  • NewAdded Support for Rad Studio 13 Florence.
  • NewAmazon SDK updated files with the latest parser.
  • NewGoogle SDK updated files with the latest parser.
  • NewAzure SDK updated files with the latest parser.
  • NewMicrosoft SDK updated files with the latest parser.

sgcOpenAPI 2025.7.0

  • FixedFixed Bug sgcVer.inc: rearrange some compiler directives to avoid incompatiblities between editions.
  • FixedFixed some minor bugs.

sgcOpenAPI 2025.6.0

  • NewImproved OpenAPI Parser: added support for OneOf elements.
  • FixedFixed Bug sgcIndy: function RSA_set0_key, only is required for openssl 1.1+.
  • FixedFixed Bug sgcIndy: decoding UTC DataTime.
  • FixedFixed Bug sgcIndy: if EVP_PKEY_base_id function is not available use the EVP_PKEY_is_a function instead.
  • FixedFixed Bug JWT: some internal openssl objects were not properly destroyed after signing or validating.
  • FixedFixed Bug JWT: error evaluating if the algorithms TIdHashSHA384 or TIdHashSHA512 were available.
  • FixedFixed Bug TsgcHTTP1Client: when calling an Async method, the default request was not assigned internally.

sgcOpenAPI 2025.5.0

  • FixedMinor bugs and fixes.

sgcOpenAPI 2025.4.0

  • FixedFixed bug in OAuth2 Client: When changing the local server port, the old port was not removed from the bindings list.

sgcOpenAPI 2025.3.0

  • NewAdded Support for Rad Studio 12.3
  • NewImproved HTTPClient, when using SChannel there is a new event "OnSChannelVerifyPeer" to validate manually the certificate.
  • NewImproved OpenAPI Google Demos, when using service account to authenticate if the subject and scope are not defined, a default value is set.
  • FixedFixed Bug sgcIdSSLOpenSSLHeaders, the method X509_STORE_CTX_free was not properly defined.
  • FixedFixed Bug sgcIdSSLOpenSSLHeader, the method ECDH_compute_key was not properly defined.

sgcOpenAPI 2025.2.0

  • NewImproved Setup, now if detects the IDE is running aborts the installation until it's closed.

sgcOpenAPI 2025.1.0

  • NewImproved OpenAPI Parser, added support for multipart/form-data requests.
  • NewImproved OpenAPI Client, added the following events: OnSSLVerifyPeer, OnSSLGetHandler and OnSSLAfterCreateHandler.
  • FixedFixed Bug OpenAPI Parser when the content of the body is "application/x-www-form-urlencoded" it was sending as json by default.
  • FixedFixed Bug OpenAPI Parser when generating the content as "application/x-www-form-urlencoded" for Dynamic Arrays.
  • FixedFixed Bug OpenAPI Parser reading class properties where the name contains characters like "[]".

Get the current release

Every licence includes a year of updates, and the trial is the full product.