Skip to main content

APIPlayground

Server-side component for rendering an interactive API playground.
import { APIPlayground } from 'fumadocs-openapi/playground';

<APIPlayground
  path="/users/{id}"
  method={methodInformation}
  ctx={renderContext}
/>

PlaygroundClient

Client-side interactive playground component.
'use client';
import PlaygroundClient from 'fumadocs-openapi/playground/client';

<PlaygroundClient
  route="/api/users"
  method="POST"
  parameters={parameters}
  securities={securities}
  body={bodySchema}
  references={schemaReferences}
/>

PlaygroundClientOptions

Configuration options for customizing the playground.
interface PlaygroundClientOptions {
  transformAuthInputs?: (fields: AuthField[]) => AuthField[];
  requestTimeout?: number;
  components?: {
    ResultDisplay?: FC<{ data: FetchResult }>;
  };
  renderParameterField?: (fieldName: FieldKey, param: ParameterField) => ReactNode;
  renderBodyField?: (fieldName: 'body', info: { schema: ParsedSchema; mediaType: string }) => ReactNode;
}

ParameterField

API parameter definition:
type ParameterField = NoReference<ParameterObject> & {
  schema: ParsedSchema;
  in: 'cookie' | 'header' | 'query' | 'path';
};

SecurityEntry

Authentication security scheme:
type SecurityEntry = SecuritySchemeObject & {
  scopes: string[];
  id: string;
};
Supported security types:
  • http: HTTP authentication (Basic, Bearer)
  • apiKey: API key authentication
  • oauth2: OAuth 2.0 authentication
  • openIdConnect: OpenID Connect

AuthField

Authentication field configuration:
interface AuthField {
  fieldName: FieldKey;
  defaultValue: unknown;
  original?: SecurityEntry;
  children: ReactNode;
  mapOutput?: (values: unknown) => unknown;
}

Custom

Hook for controlling form fields in custom renderers:
import { Custom } from 'fumadocs-openapi/playground/client';

function CustomField({ fieldName }) {
  const { value, setValue } = Custom.useController(fieldName, {
    defaultValue: '',
  });
  
  return (
    <input
      value={value}
      onChange={(e) => setValue(e.target.value)}
    />
  );
}
Returns: { value, setValue }

Example: Basic Playground

import { createAPIPage } from 'fumadocs-openapi/ui';
import { createOpenAPI } from 'fumadocs-openapi/server';

const server = createOpenAPI({
  input: ['./openapi.yaml'],
  proxyUrl: '/api/proxy',
});

export const APIPage = createAPIPage(server, {
  playground: {
    enabled: true,
  },
});

Example: Custom Result Display

export const APIPage = createAPIPage(server, {
  client: {
    playground: {
      components: {
        ResultDisplay: ({ data, reset }) => (
          <div className="border rounded-lg p-4">
            <div className="flex justify-between mb-2">
              <h3>Response</h3>
              <button onClick={reset}>Close</button>
            </div>
            <div className="mb-2">
              <span className="font-bold">Status:</span> {data.status}
            </div>
            {data.data && (
              <pre className="bg-gray-100 p-2 rounded">
                {JSON.stringify(data.data, null, 2)}
              </pre>
            )}
          </div>
        ),
      },
    },
  },
});

Example: Custom Parameter Input

import { Custom } from 'fumadocs-openapi/playground/client';

export const APIPage = createAPIPage(server, {
  client: {
    playground: {
      renderParameterField: (fieldName, param) => {
        const { value, setValue } = Custom.useController(fieldName, {
          defaultValue: param.schema.default || '',
        });
        
        return (
          <div className="mb-4">
            <label className="block font-medium mb-1">
              {param.name}
              {param.required && <span className="text-red-500">*</span>}
            </label>
            <input
              type="text"
              value={value as string}
              onChange={(e) => setValue(e.target.value)}
              className="w-full border rounded px-3 py-2"
              placeholder={param.description}
            />
          </div>
        );
      },
    },
  },
});

Example: Transform Auth Inputs

export const APIPage = createAPIPage(server, {
  client: {
    playground: {
      transformAuthInputs: (fields) => {
        // Add custom auth field
        return [
          ...fields,
          {
            fieldName: ['header', 'X-Custom-Auth'],
            defaultValue: '',
            children: (
              <FieldSet
                fieldName={['header', 'X-Custom-Auth']}
                name="Custom Auth Token"
                isRequired
                field={{ type: 'string' }}
              />
            ),
          },
        ];
      },
    },
  },
});

Example: Custom Request Timeout

export const APIPage = createAPIPage(server, {
  client: {
    playground: {
      requestTimeout: 30, // 30 seconds
    },
  },
});

Example: Disable Playground

export const APIPage = createAPIPage(server, {
  playground: {
    enabled: false,
  },
});

Example: Custom Playground Renderer

export const APIPage = createAPIPage(server, {
  playground: {
    render: ({ path, method, ctx }) => (
      <div className="border rounded-lg p-4">
        <h3>Try {method.method} {path}</h3>
        <p>Custom playground implementation</p>
        {/* Your custom playground UI */}
      </div>
    ),
  },
});

Build docs developers (and LLMs) love