Data Storage

data/ is gitignored — it holds your local collections, environments, and history as plain JSON files you fully own.

Each machine running Volley has its own independent data/ folder; there is no cloud sync and no shared state between computers. To move collections between machines, use Export / Import — export on one machine and import on another. For continuous sharing, see Sharing data/ in Getting Started, or Git Sync for a git-backed option.

On save, Volley wipes and rewrites every collection directory from the current in-memory state — renames/deletions are handled by this wipe-and-rewrite, not by diffing.

Request shape

{
  "name": "Get user",
  "method": "GET",
  "url": "https://api.example.com/users/:userId",
  "protocol": "http",
  "description": "Fetches a single user by id.",
  "params":  [{ "id": "x", "key": "include", "value": "profile", "enabled": true, "note": "" }],
  "pathVars": [{ "id": "z", "key": "userId", "value": "123" }],
  "headers": [{ "id": "y", "key": "Authorization", "value": "Bearer {{token}}", "enabled": true, "note": "Dev key" }],
  "body": {
    "type": "raw",
    "raw": "{\"key\": \"value\"}",
    "contentType": "json",
    "formData": [],
    "graphql": { "query": "", "variables": "" }
  },
  "auth": {
    "type": "bearer",
    "token": "{{token}}",
    "username": "", "password": "", "apiKey": "", "apiValue": "",
    "accessTokenUrl": "", "clientId": "", "clientSecret": "", "scope": "",
    "cachedToken": "", "cachedExpiry": 0,
    "jwtSecret": "", "jwtPayload": "{\"sub\":\"user123\"}"
  },
  "preRequestScript": "pm.environment.set('timestamp', Date.now());",
  "testScript": "pm.test('status is 200', () => pm.expect(pm.response.status).toBe(200));",
  "comments": [{ "id": "c1", "author": "Alice", "text": "Returns 404 for soft-deleted users.", "createdAt": 1718000000000 }],
  "mock": { "enabled": false, "status": 200, "headers": [], "body": "{\"id\":123,\"name\":\"Ada\"}", "delay": 0 },
  "examples": [{ "id": "e1", "name": "200 OK", "status": 200, "statusText": "OK", "headers": {}, "body": "{\"id\":123}", "bodyType": "json", "createdAt": 1718000000000 }]
}

Collections also carry a "description" field, set via right-click → "Edit Description" on a collection.

Form-data files & binary bodies

A form-data body's formData rows can be files instead of plain text values, and a "binary" body type sends a raw file as the request body:

{
  "body": {
    "type": "formdata",
    "formData": [
      { "id": "a", "key": "name",   "value": "volley",  "enabled": true, "type": "text" },
      { "id": "b", "key": "upload", "enabled": true,   "type": "file", "fileName": "photo.png", "fileSize": 12345, "fileMimeType": "image/png", "fileData": "<base64>" }
    ]
  }
}
{
  "body": {
    "type": "binary",
    "fileName": "report.pdf", "fileSize": 98765, "binaryMimeType": "application/pdf", "fileData": "<base64>"
  }
}

File contents (fileData) are stored as base64 in the request's saved JSON, sent to the server as part of /api/proxy's body, and reassembled into a multipart Blob/raw Buffer server-side.

GraphQL bodies

A "graphql" body type sends a POST (or whatever method the request uses) with a JSON body of { "query": ..., "variables": ... }, and adds a Content-Type: application/json header automatically (unless you've set your own or disabled it):

{
  "body": {
    "type": "graphql",
    "graphql": {
      "query": "query GetUser($id: ID!) { user(id: $id) { id name } }",
      "variables": "{\"id\": \"{{userId}}\"}"
    }
  }
}

Both query and variables support {{variable}} interpolation; variables is parsed as JSON when the request is sent.