Skip to navigation

Endpoints in Fern Definition

View as Markdown

Fern Definition isn’t recommended for new customers and Fern isn’t accepting feature requests for this format. It remains supported for existing users.

In Fern, you organize related endpoints into a Service. This grouping improves clarity and makes the generated SDKs more idiomatic.

Service definition

Each service defines:

  1. A base-path: A common prefix for all the endpoints’ HTTP paths
  2. Whether the service requires authentication
  3. Endpoints
user.yml
service:
base-path: /users # This defines the group/namespace for the methods
auth: false
endpoints: {}

To define a service with an empty base path use the empty string: base-path: ""

Section display name

By default, section names in your API Reference come from service file names (e.g., user.yml becomes “User”). To override the display name of a section, use the section property in your docs.yml.

SDK method names

SDK method names are derived directly from the service file name and endpoint key. The file name becomes the namespace and the endpoint key becomes the method name.

For example, given the following definition:

users.yml
service:
base-path: /users
auth: false
endpoints:
create:
path: ""
method: POST
request: CreateUserRequest

Fern generates a method called client.users.create().

Endpoints

An endpoint includes:

  • A URL path (Optionally including path parameters)
  • A Display Name (Optional)
  • An HTTP Method
  • Request information (Optional)
    • Query-parameters
    • Headers
    • Request body
  • Successful (200) response information (Optional)
  • Error (non-200) responses that this endpoint might return (Optional)

URL path

Each endpoint has a URL path.

user.yml
service:
base-path: /users
auth: false
endpoints:
getAllUsers:
path: /all
method: GET

The full path for the endpoint is the concatenation of:

  • The environment URL
  • The service base-path
  • The endpoint path

Endpoint display name

The display name will appear as the title of an endpoint. By default, the display name is equal to the ‘Title Case’ of the endpoint name. If you would like to customize the endpoint name, you can set the display name.

In the example below, “Add a new plant to the store” displays as the title of the endpoint page within the API Reference.

user.yml
service:
base-path: /v3
auth: false
endpoints:
addPlant:
path: /plant
display-name: Add a new plant to the store
method: POST

Path parameters

Supply path parameters for your endpoints to create dynamic URLs.

user.yml
service:
base-path: /users
auth: false
endpoints:
getUser:
path: /{userId}
path-parameters:
userId: string
method: GET

Services can also have path-parameters:

project.yml
service:
base-path: /projects/{projectId}
path-parameters:
projectId: string
auth: false
endpoints:
...

A path parameter can’t share a name with another request property (a body property, query parameter, or header), including after camelCase normalization. fern check reports these collisions; set the name property on the path parameter to rename it and resolve the collision:

user.yml
path-parameters:
plantId:
type: string
name: id

Query parameters

Each endpoint can specify query parameters:

user.yml
service:
base-path: /users
auth: false
endpoints:
getAllUsers:
path: /all
method: GET
request:
# this name is required for idiomatic SDKs
name: GetAllUsersRequest
query-parameters:
limit: optional<integer>

allow-multiple

Use allow-multiple to specify that a query parameter is allowed multiple times in the URL, as in ?filter=jane&filter=smith. This will alter the generated SDKs so that consumers can provide multiple values for the query parameter.

user.yml
...
query-parameters:
filter:
type: string
allow-multiple: true

Auth

Each endpoint can override the auth behavior specified in the service.

user.yml
service:
base-path: /users
auth: false
endpoints:
getMe:
path: ""
method: GET
# This endpoint will be authed
auth: true
docs: Return the current user based on Authorization header.

Headers

Each endpoint can specify request headers:

user.yml
service:
base-path: /users
auth: false
endpoints:
getAllUsers:
path: /all
method: GET
request:
# this name is required for idiomatic SDKs name:
name: GetAllUsersRequest
headers:
X-Endpoint-Header: string

Services can also specify request headers. These headers will cascade to the service’s endpoints.

user.yml
service:
base-path: /users
auth: false
headers:
X-Service-Header: string
endpoints:
getAllUsers:
path: /all
method: GET
request:
# this name is required for idiomatic SDKs
name: GetAllUsersRequest
headers:
X-Endpoint-Header: string

Request body

Endpoints can specify a request body type.

user.yml
service:
base-path: /users
auth: false
endpoints:
setUserName:
path: /{userId}/set-name
path-parameters:
userId: string
method: POST
request: string

Inlining a request body

If the request body is an object, you can inline the type declaration. This makes the generated SDKs a bit more idiomatic.

user.yml
service:
base-path: /users
auth: false
endpoints:
createUser:
path: /create
method: POST
request:
# this name is required for idiomatic SDKs
name: CreateUserRequest
body:
properties:
userName: string

Success response

Endpoints can specify a response, which is the type of the body that will be returned on a successful (200) call.

user.yml
service:
base-path: /users
auth: false
endpoints:
getAllUsers:
path: /all
method: GET
response: list<User>
types:
User:
properties:
userId: string
name: string

Response status codes

You can also use the status-code field to specify a custom status code for a success response.

user.yml
service:
base-path: /users
auth: false
endpoints:
create: :
path: ""
method: POST
request: CreateUserRequest
response:
type: User
status-code: 201
types:
User:
properties:
userId: string
name: string

An endpoint has exactly one success response: response takes a single type and a single status-code. There is no array of success responses. To document a second success body shape, model the response type as a discriminated or undiscriminated union, which still renders under one status code. Non-success responses are declared as errors.

Pagination

Fern supports offset, cursor, URI, and path-based pagination schemes. To set up auto-pagination in generated SDKs:

  1. Annotate the desired paginated endpoint with the pagination field
  2. Specify the pagination scheme (offset, cursor, next_uri, or next_path)
  3. Specify where your results are located using dot-access notation.
Offset pagination options

Include step in most offset pagination configurations to ensure the offset increments by the page size. Use has-next-page when your API returns a boolean indicator for additional pages.

service:
base-path: /users
auth: false
endpoints:
list:
path: ""
method: GET
pagination:
offset: $request.page
step: $request.page_size # Recommended
results: $response.data
has-next-page: $response.has_more
request:
name: ListUsersRequest
query-parameters:
page: optional<integer>
page_size: optional<integer>
response: ListUsersResponse
types:
ListUsersResponse:
properties:
data: list<User>
has_more: boolean

The pagination field supports the following properties:

PropertyDescription
offsetPath to the offset parameter in the request (e.g., $request.page)
cursorPath to the cursor parameter in the request (e.g., $request.cursor)
next_cursorPath to the next cursor value in the response (required for cursor pagination)
next_uriPath to the next page’s URL in the response (e.g., $response.next_page_url)
next_pathPath to the relative path for the next page in the response (e.g., $response.next_page_path)
resultsPath to the results array in the response (e.g., $response.data)
stepPath to the page size parameter, ensures offset increments correctly
has-next-pagePath to a boolean indicator for additional pages

Idempotent endpoints

Mark an endpoint as idempotent to allow SDK users to specify idempotency headers for safe request retries. You must also configure idempotency headers in your api.yml to define which headers are available.

service.yml
service:
base-path: /transactions
auth: true
endpoints:
send:
path: ""
method: POST
idempotent: true
request: SendTransactionRequest
response: Transaction

Error responses

Endpoints can specify error responses, which detail the non-200 responses that the endpoint might return.

user.yml
service:
base-path: /users
auth: false
endpoints:
getUser:
path: /{userId}
path-parameters:
userId: string
method: GET
response: User
errors:
- UserNotFoundError
types:
User:
properties:
userId: string
name: string
errors:
UserNotFoundError:
status-code: 404

You can learn more about how to define errors on the Errors page.

Specifying examples

When you declare an example, you can also specify some examples of how that endpoint might be used. These are used by the compiler to enhance the generated outputs. Examples will show up as comments in your SDKs, API documentation, and Postman collection.

You may add examples for endpoints, types, and errors.

user.yml
service:
base-path: /users
auth: false
endpoints:
getUser:
path: /{userId}
path-parameters:
userId: string
method: GET
response: User
errors:
- UserNotFoundError
examples:
- path-parameters:
userId: alice-user-id
response:
body:
userId: alice-user-id
name: Alice
types:
User:
properties:
userId: string
name: string
errors:
UserNotFoundError:
status-code: 404

If you’re adding an example to an endpoint and the type already has an example, you can reference it using $.

service:
auth: true
base-path: /address
endpoints:
create:
method: POST
path: ""
request: CreateAddress
response: Address
examples:
- request: $CreateAddress.WhiteHouse
response:
body: $Address.WhiteHouseWithID
CreateAddress:
properties:
street1: string
street2: optional<string>
city: string
state: string
postalCode: string
country: string
isResidential: boolean
examples:
- name: WhiteHouse
value:
street1: 1600 Pennsylvania Avenue NW
city: Washington DC
state: Washington DC
postalCode: "20500"
country: US
isResidential: true
Address:
extends: CreateAddress
properties:
id:
type: uuid
docs: The unique identifier for the address.
examples:
- name: WhiteHouseWithID
value:
id: 65ce514c-41e3-11ee-be56-0242ac120002
street1: 1600 Pennsylvania Avenue NW
city: Washington DC
state: Washington DC
postalCode: "20500"
country: US
isResidential: true

Examples contain all the information about the endpoint call, including the request body, path parameters, query parameters, headers, and response body.

user.yml
examples:
- path-parameters:
userId: some-user-id
query-parameters:
limit: 50
headers:
X-My-Header: some-value
response:
body:
response-field: hello

Failed examples

You can also specify examples of failed endpoints calls. Add the error property to a response example to designate which failure you’re demonstrating.

user.yml
examples:
- path-parameters:
userId: missing-user-id
response:
error: UserNotFoundError
errors:
UserNotFoundError:
status-code: 404

If the error has a body, then you must include the body in the example.

user.yml
examples:
- path-parameters:
userId: missing-user-id
response:
error: UserNotFoundError
body: "User with id `missing-user-id` was not found"
errors:
UserNotFoundError:
status-code: 404
type: string

Referencing examples from types

To avoid duplication, you can reference examples from types using $.

user.yml
service:
base-path: /users
auth: true
endpoints:
getUser:
method: GET
path: /{userId}
path-parameters:
userId: UserId
examples:
- path-parameters:
userId: $UserId.Example1
types:
UserId:
type: integer
examples:
- name: Example1
value: user-id-123