SDK customization options
The customizations
section is used to customize your SDKs.
Setting | Type | Required | Default | Description |
---|---|---|---|---|
authentication | object | ❌ | N/A | Customization the API authentication settings |
documentation | object | ❌ | N/A | Customization the documentation generation settings |
generateEnv | bool | ❌ | true | Should example .env files be generated? |
license | object | ❌ | N/A | What license should the SDKs be covered under? |
retry | object | ❌ | N/A | Retry functionality customization |
injectedModels | array | ❌ | N/A | A list of models to inject into their parent models |
environmentVariables | array | ❌ | N/A | A list of environment variables to inject into the SDKs |
refreshToken | object | ❌ | N/A | Refresh token customization |
environments | array | ❌ | N/A | A list of deployment environments |
inferServiceNames | bool | ❌ | false | Should the SDKs infer service names from the spec? |
responseHeaders | bool | ❌ | false | Should response headers be included in the response object. |
devContainer | bool | ❌ | false | Should the generated SDKs contain the files to be able to run it as a dev container |
includeOptionalSnippetParameters | bool | ❌ | true | Should optional parameters be included in the code snippets in generated documentation |
buildAllModels | bool | ❌ | false | Should build models that are not directly used by the services |
endpointCustomizations | object | ❌ | N/A | Customize an endpoint based on a path and method name |
readme | object | ❌ | N/A | Overwrites the SDK README description |
authentication
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
The authentication
options allow you to configure the authentication that your API uses, that is set using the auth
options. This section is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
access | object | ❌ | N/A | Custom access token authentication options |
apiKey | object | ❌ | N/A | API key authentication options |
You can read more on authentication in our authentication guide.
access
The access
options allow you to configure the custom access token that is sent to your API when the auth
option is set to custom
. This section is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
prefix | string | ❌ | N/A | The prefix to use for the custom access token authentication |
prefix
The prefix
is used to define a custom prefix when using an access token. By default when using custom access token authentication, the Authorization
header is passed as Bearer <token>
. For example, if your bearer token is Passw0rd123!
, the header would be:
Header | Value |
---|---|
Authorization | Bearer Passw0rd123! |
By setting the prefix
, you can replace Bearer
with the value of your choice.
For example, if you have the following:
{
...
"auth": [
"custom"
],
"customizations": {
"authentication": {
"access": {
"prefix": "Token"
}
}
}
...
}
Then the header would be:
Header | Value |
---|---|
Authorization | Token Passw0rd123! |
apiKey
The apiKey
option is used to configure the API key authentication for the SDKs. This is used if the auth
setting is set to apikey
. This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
header | string | ❌ | X-API-KEY | The header to use for the API key authentication |
header
The header
option sets the header to use for the API key authentication. This is used by the SDKs to set the header when making requests to the API. For example, if you have the following:
{
...
"customizations": {
"authentication": {
"apiKey": {
"header": "MY_CUSTOM_APIKEY_HEADER"
}
}
}
...
}
Then the API key will be passed to your API using the MY_CUSTOM_APIKEY_HEADER
header.
If this is not set, then API keys by default will be passed using the X-API-KEY
header.
documentation
The documentation
options allow you to configure the documentation that is generated with your SDK. You define what types of documentation is created using the the docs
options. This section is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
snippets | object | ❌ | N/A | SDK snippets customization options |
enhancedApiSpec | object | ❌ | N/A | Enhanced OpenAPI spec customization options |
You can read more about documentation generation in our documentation generation guide.
snippets
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ❌ ✅ ❌ ✅ ✅ ✅ ✅ ✅ ✅
The snippets
options allow you to configure the code snippets that are generated in the documentation. This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
format | string | ❌ | markdown | The format of the code snippets |
format
The format of the code snippets that are generated in the documentation.
Valid values are:
Value | Description |
---|---|
markdown | Generate snippets as markdown |
json | Generate snippets as JSON |
enhancedApiSpec
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ❌ ✅ ❌ ✅ ❌ ✅ ✅ ✅ ✅
The enhancedApiSpec
options allow you to configure the enhanced OpenAPI spec that is generated in the documentation. This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
customOutputName | string | ❌ | enhancedApiSpec.json | The format of the enhanced OpenAPI spec file |
customOutputName
The format of the enhanced OpenAPI specification file.
Valid values are: <fileName>.json
, <fileName>.yaml
and <fileName>.yml
generateEnv
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ❌ ✅ ❌ ✅ ❌ ❌ ✅ ❌
If this option is set to true
, then an example .env
file is created in the SDK with the name .env.example
to set environment variables for authentication. This can be used by your SDK users to configure their environment variables.
For example, if you have an API that uses a bearer token then this will need to be passed to the SDK on initialization, and it is good practice for this to be read from an environment variable or other configuration instead of being hard coded.
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
In TypeScript you would initialize the SDK using code like this:
import { ExcitingSoda } from 'excitingsoda';
const sdk = new ExcitingSoda({ accessToken: process.env.EXCITINGSODA_ACCESS_TOKEN });
The EXCITINGSODA_ACCESS_TOKEN
environment variable will be defined in the .env.example
:
EXCITINGSODA_ACCESS_TOKEN=
The naming convention of .env.example
is standard practice as .env
files are normally not committed to source code control, and are usually ignored in .gitignore
files.
This feature is not currently supported with TypeScript v2 SDKs.
In Java you would initialize the SDK using code like this:
import soda.exciting.ExcitingSoda;
public class Main {
public static void main(String[] args) {
ExcitingSoda client = new ExcitingSoda(System.getenv("EXCITINGSODA_ACCESS_TOKEN"));
}
}
The EXCITINGSODA_ACCESS_TOKEN
environment variable will be defined in the .env.example
:
EXCITINGSODA_ACCESS_TOKEN=
The naming convention of .env.example
is standard practice as .env
files are normally not committed to source code control, and are usually ignored in .gitignore
files.
This feature is not currently supported with Java v2 SDKs.
In Python you would initialize the SDK using code like this:
from os import getenv
from excitingsoda import ExcitingSoda
sdk = ExcitingSoda()
sdk.set_access_token(getenv("EXCITINGSODA_ACCESS_TOKEN"))
The EXCITINGSODA_ACCESS_TOKEN
environment variable will be defined in the .env.example
:
EXCITINGSODA_ACCESS_TOKEN=
The naming convention of .env.example
is standard practice as .env
files are normally not committed to source code control, and are usually ignored in .gitignore
files.
This feature is not currently supported with Python v2 SDKs.
This feature is not currently supported with C# SDKs.
In Go you would initialize the SDK using code like this:
import (
"os"
"github.com/exciting-soda/exciting-soda-go-sdk/pkg/excitingsoda"
"github.com/exciting-soda/exciting-soda-go-sdk/pkg/excitingsodaconfig"
"github.com/exciting-soda/exciting-soda-go-sdk/pkg/pets"
)
func main() {
loadEnv()
config := excitingsodaconfig.NewConfig()
config.SetAccessToken(os.Getenv("ACCESS_TOKEN"))
client := excitingsoda.NewExcitingSoda(config)
}
The default example code includes a helper function called loadEnv
that reads the .env
file and sets the environment variables. The ACCESS_TOKEN
environment variable is used to set the access token in the config
object.
The ACCESS_TOKEN
environment variable will be defined in the .env.example
:
ACCESS_TOKEN=
This feature is not currently supported with PHP SDKs.
license
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
The license
option sets the open source license for the SDKs, if wanted. This is used in the LICENSE
file that is created with the SDKs, as well as in the package manifests (such as the TypeScript package.json
or Java pom.xml
files). This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
type | string | ❌ | NONE | The type of license to use. If this is not set, the default is to not set a license |
url | string | ❌ | "" | The URL of a custom license if the type is set to CUSTOM |
type
The type of license - such as one of a set of popular licenses, or a custom license.
Valid values are:
Value | Description |
---|---|
MIT | MIT |
GPL3 | GPL 3.0 |
APACHE | Apache 2.0 |
NONE | No license information will be set |
CUSTOM | Use a custom license |
For example, to use an MIT license for your SDK:
{
...
"customizations": {
"license": {
"type": "MIT"
}
},
...
}
If you set this to CUSTOM
, then you will need to set the url
to the URL of the license file to use.
url
The URL to a custom license file. The liblab CLI will need to be able to access this file, so the remote URL will need to be public, for example a source-available Business Source License (BSL) license available publicly on your website or in a public GitHub repo.
This is only used if the type
option is set to CUSTOM
. For example, to point the SDK to a custom license file, use the following:
{
...
"customizations": {
"license": {
"type": "CUSTOM",
"url": "https://exciting.soda/sdk/license.txt"
}
},
...
}
You can find a list of OSI approved licenses on the Open Source Initiative licenses page.
retry
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
The retry
setting is used to configure the retry functionality for the SDKs. This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
enabled | bool | ❌ | false | Should retry functionality be enabled? |
maxAttempts | integer | ❌ | 3 | The maximum number of attempts to retry |
retryDelay | integer | ❌ | 150 | The delay between retries in milliseconds |
If this setting is not set, the SDKs will not have retry functionality enabled.
enabled
The enabled
option determines whether or not retry functionality is enabled. If this is set to true
, then the SDK will retry requests that fail due to network errors or server errors. If this is set to false
, then the SDK will not retry requests.
maxAttempts
The maxAttempts
option sets the maximum number of attempts to retry a request. For example, if this is set to 3
, then the SDK will retry a request up to 3 times before giving up.
retryDelay
The retryDelay
option sets the delay between retries in milliseconds. For example, if this is set to 150
, then the SDK will wait 150 milliseconds between retries.
More retry options
An extended set of retry options is available in some languages.
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ❌ ❌ ❌ ✅ ❌ ❌ ❌ ❌ ❌
For languages that support extended retry options, you can set the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
retryDelayJitter | number | ❌ | 50 | The jitter to use in the retry delay |
backOffFactor | number | ❌ | 2 | The backoff factor to use for exponential backoff |
maxDelay | number | ❌ | 5000 | The maximum delay in milliseconds between retries |
httpCodesToRetry | array | ❌ | [408, 429, 500, 502, 503, 504] | The HTTP codes to retry |
httpMethodsToRetry | array | ❌ | ["GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"] | The HTTP methods to retry |
retryDelayJitter
The retryDelayJitter
option sets the jitter to use in the retry delay. For example, if this is set to 50
, then the SDK will vary the delay between retries by a random number between 0 and 50 milliseconds.
backOffFactor
The backOffFactor
option sets the backoff factor to use for exponential backoff. For example, if this is set to 2
, then the SDK will double the amount of time between retries on each retry.
maxDelay
The maxDelay
option sets the maximum delay in milliseconds between retries. For example, if this is set to 5000
, then the maximum delay between retries will capped at 5 seconds.
httpCodesToRetry
The httpCodesToRetry
option delimits the response HTTP status codes on which the SDK should retry.
httpMethodsToRetry
The httpMethodsToRetry
option delimits the HTTP methods on which the SDK should retry.
injectedModels
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ❌ ✅ ❌ ✅ ❌ ❌ ❌ ❌
When liblab generates an SDK, it creates models for the request and response objects, as well as the different schemas defined in the components section of the API spec. Some schemas are composed of other schemas, and these are by default created as separate models.
For example, if you have:
"Message": {
"properties": {
"message": {
"type": "string",
"title": "Message"
},
"body": {
"$ref": "#/components/schemas/MessageBody"
}
},
"type": "object",
},
"MessageBody": {
"properties": {
"details": {
"type": "string",
"title": "Details"
}
},
"type": "object"
}
Then the SDK will create 2 models, Message
and MessageBody
. If you don't want the separate MessageBody
model created, you can add "MessageBody"
to the injectedModels
array, and the MessageBody
model will be injected into the Message
model:
{
...
"customizations": {
"injectedModels": [
"MessageBody"
]
},
...
}
You will get the following:
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
export interface Message {
message: string;
body: Body;
}
interface Body {
details: string;
}
This feature is not currently supported with TypeScript v2 SDKs.
public class Message extends soda.exciting.models.BaseModel {
public static class Body extends soda.exciting.models.BaseModel {
private final java.lang.String details;
}
private final Message.Body body;
private final java.lang.String message;
}
This feature is not currently supported with Java v2 SDKs.
class Body(BaseModel):
def __init__(self, details: str, **kwargs):
self.details = details
class Message(BaseModel):
def __init__(self, body: Body, message: str, **kwargs):
self.body = body
self.message = message
This feature is not currently supported with Python v2 SDKs.
This feature is not currently supported with C# SDKs.
This feature is not currently supported with Go SDKs.
This feature is not currently supported with PHP SDKs.
environmentVariables
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ❌ ✅ ✅ ❌ ✅ ❌
The environmentVariables
setting allows you to define environment variables that need to be set by the SDK user for the SDK to work - for example if you need values set that are used in code you create in a hook.
This setting is an array of objects, with each object having the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
name | string | ✅ | N/A | The name of the environment variable |
description | string | ✅ | N/A | The value of the environment variable |
These environment variables will be declared in the .env.example
files that are created with each SDK (assuming this is enabled with the generateEnv
setting). They will also be documented in the README for the SDK.
For example, if you have the following:
{
...
"environmentVariables" : [
{
"name": "TEAM_NAME",
"description": "The team name for the SDK user"
}
],
...
}
This will add the following to the .env.example
file:
TEAM_NAME=
And the following to the README:
## Environment Variables
You will need the following environment variables in order to access all the features of this SDK:
| Name | Description |
| :-------- | :----------------------------- |
| TEAM_NAME | The team name for the SDK user |
name
The name for the environment variable.
description
The description for the environment variable. This is used for the README file only.
refreshToken
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ❌ ✅ ❌ ✅ ✅ ✅ ✅ ❌
The refreshToken
setting is used to configure the refresh token functionality for the SDKs, to allow the SDK user to remain authenticated after their authentication expires. This is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
endpoint | string | ✅ | N/A | The endpoint to use for refreshing the token |
bearerKey | string | ✅ | N/A | The response property to use to get the bearer token from the response |
refreshKey | string | ✅ | N/A | The response property to use to get the refresh token from the response |
If your API supports refresh tokens for authentication, then this needs to be set. If this section is not set, then the SDKs will not have refresh token functionality enabled. You can read more about refresh tokens in our authentication guide.
These values need to match your spec - the endpoint
needs to be defined as a supported path that can receive POST requests, and the bearerKey
and refreshKey
must be valid fields in the response from the endpoint.
endpoint
This is the endpoint to use to refresh the token.
bearerKey
The bearerKey
is the name of the key in the response from the refresh token endpoint that contains the access token that the SDK can use to continue authenticating with the API.
For example, if this is the response from the endpoint that is defined in your API spec:
"RefreshTokenPair": {
"properties": {
"accessToken": {
"type": "string"
},
"refreshToken": {
"type": "string"
}
},
"required": [
"accessToken",
"refreshToken"
],
"type": "object"
},
Then the bearerKey
should be set to accessToken
:
{
"customizations": {
"refreshToken": {
...
"bearerKey": "accessToken"
}
}
}
refreshKey
The refreshKey
is the name of the key in the response from the refresh token endpoint that contains the refresh token that the SDK can use to continue refreshing the access token with the API.
For example, if this is the response from the endpoint that is defined in your API spec:
"RefreshTokenPair": {
"properties": {
"accessToken": {
"type": "string"
},
"refreshToken": {
"type": "string"
}
},
"required": [
"accessToken",
"refreshToken"
],
"type": "object"
},
Then the refreshKey
should be set to refreshToken
:
{
"customizations": {
"refreshToken": {
...
"refreshKey": "refreshToken"
}
}
}
environments
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
Your API may have multiple environments or locations, such as preview
and production
, or NorthAmerica
, EMEA
, and APAC
. This setting allows you to configure environments to be added to the SDKs as constant values that are passed in when creating the SDK client.
This is an array of objects, with each object having the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
name | string | ✅ | N/A | The name of the environment |
url | string | ✅ | N/A | The URL for the environment |
You can read more about configuring URLs and setting these at run time in our URLs and environments guide.
name
The name
option sets the name of the environment. This is used as the name of the constant in the SDK, and is used when creating the SDK client. This name must not have any invalid characters that would not be allowed in constant names. For example, DevNA
is valid, Dev NA
is not.
url
The url
option sets the URL for the environment. This is used as the value of the constant in the SDK, and is used when creating the SDK client. This is validated to ensure it is a valid URL.
inferServiceNames
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ❌ ✅ ❌ ✅ ❌ ❌ ❌ ❌
The inferServiceNames
flag determines if service names for the SDK should be inferred from the endpoint names rather than tags
if they all share a common prefix.
The OpenAPI specification has tags
that are used to group service endpoints. For example:
tags:
- name: Boba
description: Operations for boba
- name: Soda
description: Operations for soda
paths:
"/boba":
get:
tags:
- Boba
...
"/boba/{id}":
post:
tags:
- Boba
...
"/soda":
get:
tags:
- Soda
...
In this case, the Boba
tag is used to group the GET and POST operations for the /boba
endpoints, and the Soda
tag is used for the /soda
endpoint. Using tags means the services in your SDK will be created based on these tags - for example in this case you would have a BobaService
with methods to get and post boba, and a SodaService
with a method to get soda.
tags
are optional, so you many not have these defined in your spec. You may also have a common prefix to your endpoint, such as a version number:
paths:
"/v2/boba":
get:
...
"/v2/boba/{id}":
post:
...
"/v2/soda":
get:
...
In this case the liblab CLI would default to creating a V2Service
service with methods to get and post boba, and get soda. This may not be what you want, you may want to have a BobaService
and SodaService
service instead.
To avoid this set the inferServiceNames
option to true
to infer the service names from the endpoint paths.
{
...
"customizations": {
"inferServiceNames": true
},
...
}
In this case, this would look at all the endpoints, and if they have a common prefix, then this would be ignored for the service names. Instead of a V2Service
service, you would get a BobaService
and SodaService
.
This only works if your endpoints all have the same common prefix. For example, if you have some endpoints that are v2
and some that are v3
then service names cannot be inferred, as this may lead to name clashes (for example both services having a GET endpoint for boba
). In this case, it is recommended to use tags in your OpenAPI spec.
responseHeaders
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ❌ ✅ ❌ ✅ ❌ ❌ ✅* ❌ noteResponse headers are always included in the Go SDKs by default.
When responses come back from API calls, they can contain data, as well as important information in the headers. By default, the SDKs will only return the data from the response, and ignore the headers. If you want to include the headers in the response, then set this option to true
.
For example, if you have a response object like this:
paths:
/soda/{id}:
get:
operationId: getSoda
parameters:
- name: id
in: path
required: true
description: The id of the soda
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: '#/components/schemas/Soda'
components:
schemas:
Soda:
type: object
properties:
name:
type: string
id:
type: string
If the response headers option is not set, or set to false
, then the generated getSoda
method will look like this:
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
async getSoda(id: string): Promise<Soda> {
...
}
This feature is not currently supported with TypeScript v2 SDKs.
public soda.exciting.models.Soda getSoda(String id) throws ApiException {
...
}
public Soda getSoda(@NonNull String id) throws ApiException {
...
}
def get_soda(self, id: str) -> SodaModel:
...
def get_soda(self, id: str) -> SodaModel:
...
public async Task<Soda> GetSodaAsync(string id)
Setting this option to
false
is not supported. Go SDKs will always include headers in the response.
This feature is not currently supported with PHP SDKs.
If you set the response headers option to true
:
{
...
"customizations": {
"responseHeaders": true
},
...
}
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
The the return values from calls to the SDK services will be a wrapper object containing the response data, as well as a dictionary of the headers. The getSoda
method will look like this:
async getSoda(id: string): Promise<Response<Soda>> {
With the Response<T>
type looking like this:
export default interface Response<T> {
data: T;
headers: Record<string, string>;
}
If this call returned a header such as Content-Range
, this would be in the headers
dictionary.
This feature is not currently supported with TypeScript v2 SDKs.
The the return values from calls to the SDK services will be a wrapper object containing the response data, as well as a dictionary of the headers. The getSoda
method will look like this:
public ResponseWithHeaders<soda.exciting.models.Soda> getSoda(String id) throws ApiException
With the ResponseWithHeaders<T>
class looking like this:
public class ResponseWithHeaders<T> {
private T data;
private Headers headers;
public ResponseWithHeaders(T data, Headers headers) {
this.data = data;
this.headers = headers;
}
public T getData() {
return data;
}
public Headers getHeaders() {
return headers;
}
}
If this call returned a header such as Content-Range
, this would be in the Headers
dictionary.
This feature is not currently supported with Java v2 SDKs.
The the return values from calls to the SDK services will be a wrapper object containing the response data, as well as a dictionary of the headers. The get_soda
method will look like this:
def get_soda(self, id: str) -> ResponseWithHeaders:
With the ResponseWithHeaders
type looking like this:
class ResponseWithHeaders:
def __init__(self, data, headers):
self.data = data
self.headers = headers
If this call returned a header such as Content-Range
, this would be in the headers
dictionary.
This feature is not currently supported with Python v2 SDKs.
This feature is not currently supported with C# SDKs.
All response objects returned by Go SDKs include metadata that includes response Headers, and the HTTP status code returned from the request. For example, the GetSoda
method will look like this:
func (api *SodaService) GetSoda(ctx context.Context, id string)
(*shared.ExcitingSodaResponse[Soda], *shared.ExcitingSodaError) {
}
With the shared.ExcitingSodaResponse[Soda]
object including the response headers and status code as metadata:
type ExcitingSodaResponse[T any] struct {
Data T
Metadata ExcitingSodaResponseMetadata
}
type ExcitingSodaResponseMetadata struct {
Headers map[string]string
StatusCode int
}
This feature is not currently supported with PHP SDKs.
devContainer
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ❌ ❌ ✅
The devContainer
option determines if the generated SDKs should include the files to be able to open and run the SDK using a dev container.
A dev container is a development environment setup that is containerized using technologies like Docker, making it consistent and reproducible across different development machines. It contains everything needed for the development environment, including the programming language, dependencies, libraries, tools and extensions.
If you set this to true
, every SDK generated will include a devcontainer.json
file, allowing you to start using the SDK as soon as it's produced from inside any IDE that supports development containers, such as VS Code. Additionally, each SDK will have a VS Code launch.json
file so you can run and debug the SDK example.
{
...
"customizations": {
"devContainer": true
},
...
}
You can read more on development containers in the development containers documentation.
includeOptionalSnippetParameters
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ❌ ✅ ✅ ✅ ❌ ❌ ✅
The includeOptionalSnippetParameters
option determines if optional and deprecated parameters should be included in the code snippets in generated documentation or not.
If this is set to true
(the default), then optional parameters will be included in the code snippets in the generated documentation. If this is set to false
, then optional parameters will not be included in the code snippets in the generated documentation.
For example, if you have an endpoint with an optional parameter:
paths:
/llamas:
get:
operationId: getAllLlamas
description: Retrieve a list of all llamas
parameters:
- name: age
in: query
description: Age of the llamas to get
example: 5
required: false
schema:
type: integer
With this option set to true
, the code snippets in the generated documentation will include the optional parameter:
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
const result = await sdk.llamas.getAllLlamas({ age: 5 });
const result = await sdk.llamas.getAllLlamas();
This feature is not currently supported with Java v1 SDKs.
GetAllLlamasParameters requestParameters = GetAllLlamasParameters.builder()
.age(5L)
.build();
List<Llama> response = sdk.llamas.getAllLlamas(requestParameters);
sdk = ExcitingSoda()
results = sdk.llamas.get_all_llamas(age = 5)
sdk = ExcitingSoda()
result = sdk.llamas.get_all_llamas(age=5)
This feature is not currently supported with C# SDKs.
This feature is not currently supported with Go SDKs.
$sdk = new Client();
$response = $sdk->Llamas->getAllLlamas(age: 123);
If this option is set to false
, the code snippets in the generated documentation will not include the optional parameter:
- TypeScript v1
- TypeScript v2
- Java v1
- Java v2
- Python v1
- Python v2
- C#
- Go
- PHP
const result = await sdk.llamas.getAllLlamas();
const result = await sdk.llamas.getAllLlamas();
This feature is not currently supported with Java v1 SDKs.
List<Llama> response = sdk.llamas.getAllLlamas();
sdk = ExcitingSoda()
results = sdk.llamas.get_all_llamas()
sdk = ExcitingSoda()
result = sdk.llamas.get_all_llamas()
This feature is not currently supported with C# SDKs.
This feature is not currently supported with Go SDKs.
$sdk = new Client();
$response = $sdk->Llamas->getAllLlamas();
buildAllModels
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ❌ ✅ ❌ ✅ ❌ ✅ ✅ ✅ ✅
The buildAllModels
option determines if liblab should build all models, including the ones that are not returned by the SDK's services.
For example, if you set buildAllModels
to true
, then liblab will build the models that correspond to the errors that are returned by an API, such as the models for 4XX responses.
endpointCustomizations
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
The endpointCustomizations
setting is used to customize various HTTP methods on API endpoints. This is an object with the following structure:
{
...
"customizations": {
"endpointCustomizations": {
"/pets": {
"get": { ... }
}
}
}
...
}
Supported HTTP methods:
get post put delete patch ✅ ✅ ✅ ✅ ✅
Each endpoint path and HTTP method combo that appears in your OpenAPI spec has the following customization options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
operationId | string | ❌ | N/A | A new operationId name |
operationId
This customization allows you to override an existing or missing operationId for a specific endpoint path and HTTP method combination. For example, if your OpenAPI specification contains the following endpoint and you want to change its operationId:
{
...
"paths": {
"/pets": {
"get": {
"operationId": "123aBadOperationId",
}
...
}
...
}
...
}
You can override the existing operationId without directly altering your OpenAPI spec by using the operationId customization with a new name:
{
...
"customizations": {
"endpointCustomizations": {
"/pets": {
"get": {
"operationId": "getPets"
}
}
}
}
...
}
Now the final SDK will be generated with the customized operationId:
- TypeScript Example Before Customization
- TypeScript Example After Customization
async 123aBadOperationId(params?: 123aBadOperationIdParams, requestConfig?: RequestConfig): Promise<HttpResponse<Pet[]>> {
...
}
async getPets(params?: getPetsParams, requestConfig?: RequestConfig): Promise<HttpResponse<Pet[]>> {
...
}
streaming
This customization allows you to add streaming support for a specific endpoint path and HTTP method combination.
Adding streaming support means that the SDK will return one or more responses for a single HTTP call. This is useful when you have an endpoint that returns a stream of data, such as the tokens resulting from a call to a Large Language Model (AI model).
Notes:
- Currently this feature is only supported in Python v2.
- Streaming support is automatically added for endpoints that return a
text/event-stream
content type.
For example, if your OpenAPI specification contains the following endpoint and you want to add streaming support to it:
{
...
"paths": {
"/generate": {
"post": {
"operationId": "generate",
"requestBody": {
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerateRequest"
}
}
}
},
"responses": {
"200": {
"description": "Successful response",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenerateResponse"
}
}
}
}
}
}
...
}
...
}
...
}
You can add streaming support without altering your OpenAPI spec by using the streaming
customization:
{
...
"customizations": {
"endpointCustomizations": {
"/generate": {
"post": {
"streaming": "true"
}
}
}
}
...
}
pagination
Pagination simplifies handling large datasets by managing paginated API responses automatically. It allows developers to efficiently retrieve and iterate through data page by page, eliminating the need for manual intervention. With liblab’s SDK handling pagination seamlessly, developers can focus on core functionality.
liblab provides two ways to configure pagination:
- Using the OpenAPI spec with the liblab's
x-liblab-pagination
annotation. - Using the
liblab.config.json
file to customize the necessary endpoints.
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ❌ ✅ ❌ ✅ ❌ ✅ ❌ ❌ ❌
'x-liblab-pagination' annotation
You can define pagination directly in the OpenAPI specification using the x-liblab-pagination
annotation. This approach allows pagination to be integrated directly to the API structure, as shown in the following example:
"paths": {
"/pets": {
"get": {
"operationId": "listPets",
"x-liblab-pagination": {
"paginationType": "offsetLimit",
"inputFields": [
{ "name": "offset", "in": "query", "type": "offset" },
{ "name": "limit", "in": "query", "type": "limit" }
],
"resultsArray": {
"results": "$.pets"
}
}
}
}
}
The highlighted configuration automatically adds pagination parameters (offset
and limit
) and defines how the paginated data should be extracted from the API response. The following table describes the configuration code:
Field | Type | Required | Description |
---|---|---|---|
paginationType | string | ✅ | Specifies the pagination method used to convert the received data into paginated results. The following options are available:
|
inputFields | object array | ✅ | Defines the pagination parameters sent in the API request. |
inputFields.name | string | ✅ | The parameter's name as specified in your API. The pagination parameter names must match those used by the API running on your server. Otherwise, the SDK won't function properly, since the API running in your server will not identify the pagination settings you want to apply. |
inputFields.in | string | ✅ | Specifies where in the API request the parameter is used. The following options are available:
|
inputFields.type | string | ✅ | Defines the purpose of the pagination parameter. The following options are available:
|
resultsArray | object | ✅ | Defines where the paginated results are located in the API response. |
resultsArray.results | string | ✅ | Specifies the data location in the API response. The resultsArray.results property should point to the array containing the results (e.g., $.pets ). If this is not correctly configured, errors may occur when using the SDK since the SDK expects the response to return an array. |
In addition to the annotation, you must define the pagination parameters in the OpenAPI spec. The following code block presents the parameters
definition for the same endpoint:
"paths": {
"/pets": {
"get": {
"parameters": [
{
"name": "limit",
"in": "query",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
},
{
"name": "offset",
"in": "query",
"required": true,
"schema": {
"type": "integer",
"format": "int32"
}
}
]
}
}
}
The following table describes the settings to configure the parameters
:
Field | Type | Required | Description |
---|---|---|---|
name | string | ✅ | The parameter's name. The informed name must match the names in the inputFields . |
in | string | ✅ | Specifies where the parameter will be used when performing the API request. |
required | bool | ✅ | Defines if the parameter is required when to perform the API request. |
schema | string | ✅ | Defines the parameter structure, specifying how the parameter should be formatted and validated. For the pagination feature, both the limit and offset parameters are integers, with the format int32 . |
When using the liblab pagination feature, you must set the parameters as required ("required": true
).
Customizing pagination through liblab.config.json
When the OpenAPI spec is machine-generated or unavailable for modification, you can configure pagination through the liblab.config.json
file. This allows you to store pagination settings separately from the spec, as shown in the following example:
{
"customization": {
"endpointCustomizations": {
"/pets": {
"get": {
"pagination": {
"paginationType": "limitOffset",
"inputFields": [
{
"name": "limit",
"in": "query",
"type": "limit"
},
{
"name": "offset",
"in": "query",
"type": "offset"
}
],
"resultsArray": {
"results": "$.page",
"defaultPageSize": 5
}
}
}
}
}
}
}
The fields here are similar to those in the x-liblab-pagination
annotation, with an additional option to set a default page size (defaultPageSize
). The defaultPageSize
is used as the default value for limit
if it isn't provided in the request. You must inform the defaultPageSize
parameter when configuring the pagination features through liblab.config.json
.
When using the liblab.config.json
to configure the pagination feature, you still have to define the parameters
in the OpenAPI spec. Otherwise, the SDK cannot generate accurate requests to the API. You should use the same settings to define the parameters as described before.
Paginated endpoints
Paginated endpoints are designed to handle large data sets by breaking them into smaller, manageable chunks called "pages." This approach improves performance and user experience by loading data incrementally rather than all at once. There are two common types of pagination methods:
- Iterable pagination
- Manual pagination
Access the Build a TypeScript SDK with Pagination tutorial for detailed, step-by-step guidance on implementing and using the pagination feature.
liblab pagination feature enables you to use both of these options using a simple functions easily.
- Iterable pagination
- Manual pagination
When you perform a request using liblab’s SDKs, the response returns an iterable object designed to simplify the pagination process. This object can be used directly in a for
loop, allowing you to process each data page in sequence. As you loop through the results, the SDK automatically fetches the next page behind the scenes, eliminating the need to manage each request manually.
Each paginated response contains the usual metadata, which is helpful for debugging. The actual data for each page is located inside the data
property, making it easy to retrieve and work with the results, while the SDK takes care of fetching additional pages as needed.
This approach is ideal for scenarios where you need to handle large datasets efficiently and want to process all available data without worrying about manually fetching each page.
The following code block presents an example of using the iterable pagination approach considering a TypeScript-generated SDK with a pagination feature available. An example of a paginated response is also available.
- Code example (TypeScript v2)
- Code example (Python v2)
- Code example (Java v2)
- Response example
import { TypeScriptSdk } from 'typescript-sdk';
(async () => {
const typescriptSDK = new TypeScriptSdk({
token: 'YOUR_TOKEN',
});
const pages = await typescriptSDK.petstore.petsList({
limit: 2,
offset: 5,
});
for await (const page of pages) {
console.log(page.data);
}
})();
from python_sdk import PythonSdk
sdk = PythonSdk()
pages = sdk.petstore.pets_list(
limit=2,
offset=5
)
for page in pages:
print(page)
import com.example.sdk.JavaSdk;
import com.example.sdk.models.PetsListParameters;
import com.example.sdk.models.Pet;
import java.util.List;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
JavaSdk sdk = new JavaSdk();
PetsListParameters parameters = PetsListParameters.builder()
.limit(2L)
.offset(5L)
.build();
Stream<List<Pet>> pages = sdk.petstore.petsList(parameters);
pages.forEach(System.out::println);
}
}
[
{
"id": 5,
"category": {
"id": 724,
"name": "dog"
},
"name": "Aidan",
"status": "available"
},
{
"id": 6,
"category": {
"id": 724,
"name": "dog"
},
"name": "Bella",
"status": "available"
}
],
[
{
"id": 7,
"category": {
"id": 725,
"name": "cat"
},
"name": "Whiskers",
"status": "sold"
},
{
"id": 8,
"category": {
"id": 724,
"name": "dog"
},
"name": "Max",
"status": "pending"
}
],
[
{
"id": 9,
"category": {
"id": 726,
"name": "bird"
},
"name": "Tweety",
"status": "available"
},
{
"id": 10,
"category": {
"id": 725,
"name": "cat"
},
"name": "Mittens",
"status": "available"
},
],
[
{
"id": 11,
"category": {
"id": 726,
"name": "bird"
},
"name": "Polly",
"status": "available"
},
{
"id": 12,
"category": {
"id": 724,
"name": "dog"
},
"name": "Charlie",
"status": "sold"
}
]
The response tab presents the results from the data request in a paginated format. Each page had 2 elements, defined by the limit
, and the data started from element id = 5
, since offset = 5
.
The manual pagination approach controls when to fetch the next page of data. It's ideal for scenarios where you don't need all data upfront and prefer retrieving it on demand. Using the next()
function, you can manually request the next set of results based on the specified limit and offset. This method reduces the amount of data fetched, ensuring optimal performance and lower resource consumption.
The following code block presents an example of how to use the manual pagination approach, considering a TypeScript-generated SDK with a pagination feature available. An example of a paginated response is also available.
- Code example (TypeScript v2)
- Code example (Python v2)
- Code example (Java v2)
- Response example
import { TypeScriptSdk } from 'typescript-sdk';
(async () => {
const Sdk = new TypeScriptSdk({
token: 'YOUR_TOKEN',
});
const pages = await Sdk.petstore.petList({
limit: 4,
offset: 0,
});
const firstPage = await pages.next();
console.log(firstPage.value.data);
const secondPage = await pages.next();
console.log(secondPage.value.data);
})();
from python_sdk import PythonSdk
sdk = PythonSdk()
pages = sdk.petstore.pets_list(
limit=4,
offset=0
)
try:
first_page = next(pages)
print(first_page)
second_page = next(pages)
print(second_page)
except StopIteration:
print("No more pages")
import com.example.sdk.JavaSdk;
import com.example.sdk.models.PetsListParameters;
import com.example.sdk.models.Pet;
import java.util.List;
import java.util.Iterator;
import java.util.stream.Stream;
public class Main {
public static void main(String[] args) {
JavaSdk sdk = new JavaSdk();
PetsListParameters parameters = PetsListParameters.builder()
.limit(4L)
.offset(0L)
.build();
Stream<List<Pet>> pages = sdk.petstore.petsList(parameters);
Iterator<List<Pet>> iterator = pages.iterator();
List<Pet> firstPage = iterator.next();
System.out.println(firstPage);
List<Pet> secondPage = iterator.next();
System.out.println(secondPage);
}
}
[
{
"id": 1,
"category": {
"id": 724,
"name": "dog"
},
"name": "Aidan",
"status": "available"
},
{
"id": 2,
"category": {
"id": 724,
"name": "dog"
},
"name": "Bella",
"status": "available"
},
{
"id": 3,
"category": {
"id": 725,
"name": "cat"
},
"name": "Whiskers",
"status": "sold"
},
{
"id": 4,
"category": {
"id": 724,
"name": "dog"
},
"name": "Max",
"status": "pending"
}
],
[
{
"id": 5,
"category": {
"id": 726,
"name": "bird"
},
"name": "Tweety",
"status": "available"
},
{
"id": 6,
"category": {
"id": 725,
"name": "cat"
},
"name": "Mittens",
"status": "available"
},
{
"id": 7,
"category": {
"id": 726,
"name": "bird"
},
"name": "Polly",
"status": "available"
},
{
"id": 8,
"category": {
"id": 724,
"name": "dog"
},
"name": "Charlie",
"status": "sold"
}
]
The response tab presents the results for the first and second pages required in the code example. Each page had four elements, defined by the limit
, and the data started from the beginning, since offset = 0
.
readme
Supported SDK languages and versions:
TypeScript v1 TypeScript v2 Java v1 Java v2 Python v1 Python v2 C# Go PHP ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅ ✅
The readme
option allow you to override the API description from your OpenAPI spec when generating the SDKs ReadMe file. The readme
section is an object with the following options:
Option | Type | Required | Default | Description |
---|---|---|---|---|
apiDescription | object | ❌ | N/A | Object with all customizations available for the generated ReadMe files. |
apiDescription
The apiDescription
object allows you to override the default description in the SDK's ReadMe file generated by liblab. Below are the available options within this object:
Option | Type | Required | Default | Description |
---|---|---|---|---|
[apiDescription.description ] | string | ❌ | N/A | Custom text used to replace the default description in the ReadMe file. |
Here’s an example of how to override the description in the generated ReadMe file:
{
...
"customizations": {
"readme": {
"apiDescription": {
"description": "Overwrites the SDK README description"
}
},
}
...
}