Other Extensions

Additional Fern extensions for gRPC specifications

Fern supports various extensions to enhance your gRPC specifications and improve the generated SDKs and documentation.

x-fern-ignore

Use x-fern-ignore to exclude specific services, methods or messages from SDK generation:

user_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc GetUser(GetUserRequest) returns (User);
7
8 // Exclude internal debugging method
9 rpc DebugUserData(DebugUserRequest) returns (DebugUserResponse) {
10 option (x_fern_ignore) = true;
11 }
12
13 // Exclude experimental method
14 rpc ExperimentalFeature(ExperimentalRequest) returns (ExperimentalResponse) {
15 option (x_fern_ignore) = true;
16 }
17}
18
19// Exclude internal message from SDK
20message InternalUserData {
21 option (x_fern_ignore) = true;
22
23 string internal_id = 1;
24 repeated string debug_flags = 2;
25 map<string, string> system_metadata = 3;
26}

x-fern-examples

Provide additional examples for better SDK documentation:

user_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc CreateUser(CreateUserRequest) returns (User) {
7 option (x_fern_examples) = '{
8 "StandardUser": {
9 "description": "Create a regular user account",
10 "request": {
11 "email": "john@example.com",
12 "name": "John Doe",
13 "age": 30,
14 "preferences": {
15 "theme": "dark",
16 "notifications": true
17 }
18 },
19 "response": {
20 "id": "user_123",
21 "email": "john@example.com",
22 "name": "John Doe",
23 "created_at": "2024-01-15T10:30:00Z"
24 }
25 },
26 "AdminUser": {
27 "description": "Create an admin user with special permissions",
28 "request": {
29 "email": "admin@example.com",
30 "name": "Admin User",
31 "role": "admin",
32 "permissions": ["read", "write", "delete"]
33 },
34 "response": {
35 "id": "user_456",
36 "email": "admin@example.com",
37 "name": "Admin User",
38 "role": "admin",
39 "created_at": "2024-01-15T10:30:00Z"
40 }
41 }
42 }';
43 }
44}

x-fern-pagination

Configure pagination for methods that return lists:

pagination_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc ListUsers(ListUsersRequest) returns (ListUsersResponse) {
7 option (x_fern_pagination) = '{
8 "cursor": "page_token",
9 "results": "users",
10 "next_cursor": "next_page_token",
11 "has_next_page": "has_more"
12 }';
13 }
14}
15
16message ListUsersRequest {
17 int32 page_size = 1;
18 string page_token = 2;
19 string filter = 3;
20}
21
22message ListUsersResponse {
23 repeated User users = 1;
24 string next_page_token = 2;
25 bool has_more = 3;
26 int32 total_count = 4;
27}

x-fern-retry

Configure retry behavior for methods:

retry_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc ProcessPayment(ProcessPaymentRequest) returns (PaymentResult) {
7 option (x_fern_retry) = '{
8 "max_attempts": 3,
9 "exponential_backoff": true,
10 "initial_delay_ms": 1000,
11 "max_delay_ms": 30000,
12 "retry_on_status": ["UNAVAILABLE", "DEADLINE_EXCEEDED", "INTERNAL"]
13 }';
14 }
15
16 rpc UploadFile(UploadFileRequest) returns (UploadFileResponse) {
17 option (x_fern_retry) = '{
18 "max_attempts": 5,
19 "exponential_backoff": true,
20 "initial_delay_ms": 2000,
21 "max_delay_ms": 60000
22 }';
23 }
24}

x-fern-timeout

Configure timeout settings for methods:

timeout_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc GenerateReport(GenerateReportRequest) returns (ReportResult) {
7 option (x_fern_timeout) = '{
8 "seconds": 300,
9 "description": "Report generation can take up to 5 minutes"
10 }';
11 }
12
13 rpc QuickUserLookup(UserLookupRequest) returns (User) {
14 option (x_fern_timeout) = '{
15 "seconds": 5,
16 "description": "Quick lookup should complete within 5 seconds"
17 }';
18 }
19}

x-fern-error-handling

Configure error handling for methods:

error_handling_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc CreateUser(CreateUserRequest) returns (User) {
7 option (x_fern_error_handling) = '{
8 "ALREADY_EXISTS": {
9 "error_name": "UserAlreadyExistsError",
10 "user_friendly_message": "A user with this email already exists"
11 },
12 "INVALID_ARGUMENT": {
13 "error_name": "ValidationError",
14 "user_friendly_message": "Please check your input and try again"
15 },
16 "RESOURCE_EXHAUSTED": {
17 "error_name": "RateLimitError",
18 "retry_after_seconds": 60
19 }
20 }';
21 }
22}

x-fern-availability

Mark features as available in specific SDK versions:

availability_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc GetUser(GetUserRequest) returns (User);
7
8 rpc GetUserAnalytics(GetUserAnalyticsRequest) returns (UserAnalytics) {
9 option (x_fern_availability) = '{
10 "status": "beta",
11 "message": "This feature is in beta and may change"
12 }';
13 }
14
15 rpc ExperimentalSearch(ExperimentalSearchRequest) returns (SearchResults) {
16 option (x_fern_availability) = '{
17 "status": "experimental",
18 "message": "This is an experimental feature and may be removed"
19 }';
20 }
21}

x-fern-streaming

Mark methods as streaming for appropriate SDK generation:

streaming_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 rpc StreamEvents(StreamEventsRequest) returns (stream Event) {
7 option (x_fern_streaming) = '{
8 "type": "server_streaming",
9 "termination": "client_closes"
10 }';
11 }
12
13 rpc UploadData(stream UploadDataRequest) returns (UploadResult) {
14 option (x_fern_streaming) = '{
15 "type": "client_streaming",
16 "termination": "client_closes"
17 }';
18 }
19
20 rpc Chat(stream ChatMessage) returns (stream ChatMessage) {
21 option (x_fern_streaming) = '{
22 "type": "bidirectional_streaming",
23 "termination": "either_closes"
24 }';
25 }
26}

x-fern-server-name

Specify custom names for different server environments:

server_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 option (x_fern_server_name_production) = "Production";
7 option (x_fern_server_name_staging) = "Staging";
8 option (x_fern_server_name_development) = "Development";
9
10 rpc GetUser(GetUserRequest) returns (User);
11}

x-fern-base-path

Configure base paths for generated SDK clients:

base_path_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 option (x_fern_base_path) = "/api/v1";
7
8 rpc GetUser(GetUserRequest) returns (User);
9}

x-fern-sdk-group-name

Group related services in the SDK:

grouped_services.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5service UserService {
6 option (x_fern_sdk_group_name) = "users";
7
8 rpc CreateUser(CreateUserRequest) returns (User);
9 rpc GetUser(GetUserRequest) returns (User);
10}
11
12service UserProfileService {
13 option (x_fern_sdk_group_name) = "users";
14
15 rpc GetProfile(GetProfileRequest) returns (UserProfile);
16 rpc UpdateProfile(UpdateProfileRequest) returns (UserProfile);
17}
18
19service AuthService {
20 option (x_fern_sdk_group_name) = "auth";
21
22 rpc Login(LoginRequest) returns (LoginResponse);
23 rpc Logout(LogoutRequest) returns (google.protobuf.Empty);
24}

This generates SDKs with grouped services:

1client.users.createUser(...)
2client.users.getUser(...)
3client.users.getProfile(...)
4client.users.updateProfile(...)
5client.auth.login(...)
6client.auth.logout(...)

x-fern-union-naming

Configure naming for oneof fields in SDKs:

union_naming.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5message NotificationTarget {
6 oneof target {
7 option (x_fern_union_naming) = "discriminated";
8
9 string user_id = 1 [(x_fern_parameter_name) = "userId"];
10 string group_id = 2 [(x_fern_parameter_name) = "groupId"];
11 BroadcastTarget broadcast = 3;
12 }
13}

x-fern-validation

Add validation rules for message fields:

validation_service.proto
1syntax = "proto3";
2
3package userservice.v1;
4
5message CreateUserRequest {
6 string email = 1 [
7 (x_fern_validation) = '{
8 "format": "email",
9 "required": true
10 }'
11 ];
12
13 string name = 2 [
14 (x_fern_validation) = '{
15 "min_length": 1,
16 "max_length": 100,
17 "required": true
18 }'
19 ];
20
21 int32 age = 3 [
22 (x_fern_validation) = '{
23 "minimum": 0,
24 "maximum": 120
25 }'
26 ];
27}

These extensions help you create more robust and user-friendly SDKs while maintaining full control over the generated code structure and behavior.