Skip to content

Usage ​

Basic Example ​

vue
<VueApiPlayground
  url="https://jsonplaceholder.typicode.com/posts/{id}"
  method="get"
  :data="[{ name: 'id', value: '1', type: 'number' }]"
/>

The {id} in the URL is automatically replaced with the value from the data array.

URL Path Parameters ​

Both {param} and <param> syntax are supported:

vue
<VueApiPlayground
  url="https://api.example.com/users/{userId}/posts/<postId>"
  method="get"
  :data="[
    { name: 'userId', value: '1' },
    { name: 'postId', value: '5' },
  ]"
/>

Path parameters are consumed from the data — remaining fields become query parameters (GET) or JSON body (POST/PUT/PATCH).

Props ​

PropTypeRequiredDefaultDescription
urlstringyes—API endpoint URL. Supports {param} and <param> path parameters
methodstringyes—HTTP method: get, post, put, patch, delete
dataPlaygroundDataItem[]no[]Input fields for the request
headersRecord<string, string>no—Custom HTTP headers (editable in the UI)
showMethodbooleannofalseShow HTTP method badge
showUrlbooleannofalseShow the URL above the form
headingTagstringno'h4'HTML tag for section headings
serversstring[]no—Server URLs. When more than one, a selector is rendered
contentTypePlaygroundContentTypeno—Body serialization: application/json, application/x-www-form-urlencoded, multipart/form-data, text/plain, application/xml
bodystringno—Preset request body. Active when contentType is application/json, text/plain, or application/xml. User edits take precedence
densebooleannofalseCompact layout: data fields render as a two-column grid with labels above inputs instead of a Key/Value table
v-model:authAuthConfigno{ type: 'none' }Declarative auth. See below
v-model:serverstringnofirst of serversCurrently selected base URL

Auth ​

ts
type AuthConfig =
  | { type: 'none' }
  | { type: 'bearer'; token?: string }
  | { type: 'basic'; username?: string; password?: string }
  | { type: 'apiKey'; in: 'header' | 'query'; name: string; value?: string }
  • bearer → Authorization: Bearer <token>
  • basic → Authorization: Basic base64(username:password)
  • apiKey with in: 'header' → <name>: <value> header
  • apiKey with in: 'query' → ?<name>=<value> appended to the URL

Empty values are skipped; no header or query param is attached when the field is blank.

Events ​

EventPayloadDescription
before-send{ url, init }Mutate envelope before fetch
request-start{ url, method, headers, body }Fires just before fetch()
request-success{ status, headers, body, durationMs }Fires on successful response
request-error{ error, durationMs }Fires on network / abort error

PlaygroundDataItem ​

ts
interface PlaygroundDataItem {
  name: string // field name (used as key in request)
  value: string // default value
  type?: string // semantic: 'path', 'query', 'header', 'file'; or HTML input type: 'text', 'number', 'email', 'password', 'url', 'search', 'tel'
  description?: string // shown as a subtitle below the label in dense mode
}

Semantic types (path, query, header) render as text inputs but affect request building: path parameters substitute into the URL, query parameters append to the query string, and header parameters become request headers.

Request Behavior ​

MethodData handling
GET, DELETERemaining fields appended as query string
POST, PUT, PATCHRemaining fields serialized as JSON body with Content-Type: application/json

Custom headers override the default Content-Type header for body requests.

Individual Components ​

v2 exports each component individually for custom layouts.

ApiRequest ​

A standalone request form with execute button.

vue
<script setup>
import { ApiRequest } from 'vue-api-playground'
import { ref } from 'vue'

const loading = ref(false)

function onExecute(request) {
  loading.value = true
  fetch(request.url, request.init)
    .then(/* handle response */)
    .finally(() => {
      loading.value = false
    })
}
</script>

<template>
  <ApiRequest
    url="https://api.example.com/posts"
    method="post"
    :data="[{ name: 'title', value: 'Hello' }]"
    :loading="loading"
    show-method
    @execute="onExecute"
  />
</template>
PropTypeDefaultDescription
urlstring—API endpoint URL
methodstring—HTTP method
dataPlaygroundDataItem[][]Input fields
headersRecord<string, string>—Custom headers
loadingbooleanfalseShows spinner and disables execute
showMethodbooleanfalseShow method badge
headingTagstring'h4'HTML tag for section headings
densebooleanfalseCompact two-column grid layout

Emits @execute with { url: string, init: RequestInit }.

Supports Ctrl+Enter (Cmd+Enter on Mac) to execute from any input.

Includes a collapsible Paste cURL section for importing cURL commands.

send-button slot ​

Override the default send button. The slot exposes { loading, execute, abort, streaming }:

vue
<VueApiPlayground url="https://api.example.com/events" method="get">
  <template #send-button="{ loading, execute, abort, streaming }">
    <button v-if="streaming" @click="abort">Stop</button>
    <button v-else :disabled="loading" @click="execute">
      {{ loading ? 'Sending…' : 'Send' }}
    </button>
  </template>
</VueApiPlayground>
  • loading — true while awaiting the initial fetch() response
  • streaming — true while an text/event-stream body is being read
  • execute — fires the request
  • abort — aborts the in-flight request or SSE reader; safe to call when idle

When no slot is provided, the default button automatically swaps to a Stop label while streaming is true and wires its click to abort().

ApiResponse ​

A standalone response display with copy and cURL export.

vue
<script setup>
import { ApiResponse } from 'vue-api-playground'
</script>

<template>
  <ApiResponse
    :status="200"
    :time="142"
    :headers="{ 'content-type': 'application/json' }"
    :body="{ id: 1, title: 'Hello World' }"
    :request="{ url: 'https://api.example.com/posts', method: 'GET' }"
  />
</template>
PropTypeDefaultDescription
statusnumber | null—HTTP status code
timenumber | null—Response time in ms
headersRecord<string, string> | null—Response headers
bodyunknown—Response body (JSON object or string)
requestApiResponseRequest—Original request (enables cURL button)

When body is null, the component renders nothing. When request is omitted, the cURL button is hidden.

Shows response payload size (e.g., "2.3 KB") and JSON syntax highlighting for JSON responses.

MethodBadge ​

A colored HTTP method badge.

vue
<script setup>
import { MethodBadge } from 'vue-api-playground'
</script>

<template>
  <MethodBadge method="post" />
</template>

Colors: GET = info (brand), POST = success (green), PUT/PATCH = warning (yellow), DELETE = danger (red).

Utility Functions ​

toCurl ​

Generate a cURL command from request parameters.

ts
import { toCurl } from 'vue-api-playground'

const curl = toCurl({
  url: 'https://api.example.com/posts',
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: '{"title":"Hello"}',
})
// curl -X POST -H 'Content-Type: application/json' -d '{"title":"Hello"}' 'https://api.example.com/posts'

parseCurl ​

Parse a cURL command into structured request data.

ts
import { parseCurl } from 'vue-api-playground'

const result = parseCurl(
  'curl -X POST -H \'Content-Type: application/json\' -d \'{"title":"Hello"}\' https://api.example.com/posts'
)
// { url: '...', method: 'POST', headers: {...}, body: '...', ignoredFlags: [] }

Returns null for unparseable input. Unsupported flags are listed in ignoredFlags.

Released under the MIT License.