← Back to home

First Steps

Your guide to spaces, collections, selectors, and scripts.

  1. First Launch
  2. Workspace Structure
  3. Collections — Request Files
  4. Selectors — Dynamic Dropdowns
  5. Scripts — Dynamic Values & Automation
  6. Secrets — Encrypted Local Credentials
  7. Tips & Recipes

1. First Launch

When you open Synapse for the first time, a Welcome Screen appears and asks you to choose a spaces directory — a folder on your computer where all your API projects (called spaces) will live.

Synapse remembers your choice. Next time you open the app it goes straight to your spaces.

Try Sample Project

Don't have a workspace yet? Click "Try Sample Project…" on the Welcome Screen. Pick an empty folder and Synapse exports two ready-made sample spaces into it:

The app opens the exported folder immediately — you can start sending requests right away.

2. Workspace Structure

Each space is a plain folder inside your spaces directory:

my-space/
├── workspace.json        ← space name (required)
├── collections/          ← your HTTP requests (required)
├── selectors/            ← dropdown definitions (required)
└── scripts/              ← automation scripts (optional)
Secrets are not stored in the space. They're encrypted and saved in Synapse's local config folder, outside any repository — see Secrets.

workspace.json

The only file required at the root. It holds the display name shown in the toolbar.

{
  "name": "DummyJSON API"
}

Live file watching

Synapse watches your space folder for changes. Save a JSON file from any editor and the UI updates instantly — no reload needed.

3. Collections — Request Files

Each .json file in collections/ defines one HTTP request. Sub-folders become collapsible groups in the sidebar. Prefix filenames with 01-, 02-, … to control sort order.

Field reference

FieldTypeRequiredDefaultDescription
idstringStable unique identifier. Use lowercase-kebab-case.
namestringDisplay label in the sidebar and response tabs.
methodstringGET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS.
urlstringFull URL. Supports {{...}} templates.
headersobject (string→string){}Request headers. Values support templates.
queryParamsobject (string→string){}Query parameters (?key=value). Values support templates.
bodyTypestring"none"none, json, raw, or form.
bodystring or nullnullRaw request body. For JSON, escape inner quotes with \". Supports templates.
descriptionstring or nullnullInfo text shown next to the request.
scriptLinesarray of strings[]Post-response extraction rules. See Scripts.

Templates work in url, headers, queryParams, and body — any field that accepts a string value.

Example — Login with token extraction (from the DummyJSON sample)

{
  "id": "login",
  "name": "Login",
  "method": "POST",
  "url": "{{selector.environment.BASE_URL}}/auth/login",
  "headers": {
    "Content-Type": "application/json",
    "Accept": "application/json"
  },
  "bodyType": "json",
  "body": "{\"username\":\"{{selector.credentials.USERNAME}}\",\"password\":\"{{selector.credentials.PASSWORD}}\"}",
  "scriptLines": [
    "TOKEN = response.body.accessToken",
    "REFRESH = response.body.refreshToken",
    "USER_ID = response.body.id",
    "run:parse-token"
  ]
}

This single request demonstrates:

4. Selectors — Dynamic Dropdowns

Selectors appear as dropdown chips in the toolbar. Switching a selector instantly updates every request that references it. Each selector is one .json file in selectors/.

Field reference

FieldTypeRequiredDescription
idstringUsed in templates: {{selector.<id>}} or {{selector.<id>.<KEY>}}.
namestringLabel shown in the toolbar.
defaultValuestring or nullPre-selected option value. Falls back to first option.
optionsarrayList of choices (see below).

Each option has:

FieldTypeRequiredDescription
valuestringInjected by {{selector.<id>}}.
labelstringDisplay text in the dropdown.
variablesobject (string→string)Extra key/value pairs accessed as {{selector.<id>.<KEY>}}.

Two patterns

With variables — bundle multiple config values per option (e.g. environment URLs, credentials):

{
  "id": "credentials",
  "name": "Credentials",
  "defaultValue": "emilys",
  "options": [
    {
      "value": "emilys",
      "label": "Emily Johnson",
      "variables": { "USERNAME": "emilys", "PASSWORD": "emilyspass" }
    },
    {
      "value": "michaelw",
      "label": "Michael Williams",
      "variables": { "USERNAME": "michaelw", "PASSWORD": "michaelwpass" }
    }
  ]
}

Use as {{selector.credentials.USERNAME}} and {{selector.credentials.PASSWORD}} in any request.

Without variables — the value is used directly (e.g. a product ID in a URL path):

{
  "id": "product",
  "name": "Product",
  "defaultValue": "1",
  "options": [
    { "value": "1",  "label": "Pixel 10 Pro" },
    { "value": "19", "label": "Samsung Galaxy S24 Ultra" }
  ]
}

Use as {{selector.product}} → inserts 1 or 19 directly into the URL.

Tip: You can edit selector variables directly inside Synapse — click the ⚙ Settings icon in the toolbar.

5. Scripts — Dynamic Values & Automation

A. Built-in Functions

Always available, no setup. Use in any template field.

FunctionTemplateOutput example
uuid(){{script.uuid()}}550e8400-e29b-41d4-a716-446655440000
timestamp(){{script.timestamp()}}1718358792000
isoTimestamp(){{script.isoTimestamp()}}2026-06-14T10:33:12.000Z
randomNumeric(n){{script.randomNumeric(6)}}482910
randomAlphabetic(n){{script.randomAlphabetic(9)}}xKvPtRmoQ
sign(payload,secret){{script.sign(data,mySecret)}}HMAC-SHA256 digest
base64(value){{script.base64(hello)}}aGVsbG8=

B. Script Lines (Post-Response Extraction)

Run automatically after a response. Extract values into session variables for use in subsequent requests.

Syntax: VARIABLE_NAME = source.path.to.value

Source prefixExtracts from
response.body.<key>.<key>…Response JSON body (dot-separated key chain, integer = array index)
response.headers.<header-name>Response header
request.body.<key>.<key>…Request JSON body
request.headers.<header-name>Request header

Examples:

TOKEN         = response.body.accessToken
USER_ID       = response.body.id
FIRST_ITEM    = response.body.products.0.title    # array index
TRACE_ID      = response.headers.X-Request-Id

Extracted variables are available as {{script.TOKEN}}, {{script.USER_ID}}, etc.

Note: the body path is a simple dot-separated key walk, not JSONPath. Wildcards, $, and filters are not supported.

C. Custom Kotlin Scripts (.kts)

For complex logic — JWT decoding, HMAC signatures, multi-step transformations. Place .kts files in the scripts/ folder and trigger them with run:<name> in scriptLines.

Example — decode a JWT and extract the user ID:

scripts/parse-token.kts

import java.util.Base64

val token = context.variables["TOKEN"] ?: error("TOKEN not set — send Login first")
val payloadJson = String(Base64.getUrlDecoder().decode(token.split(".")[1]))

val idMatch = """"id"\s*:\s*(\d+)""".toRegex().find(payloadJson)
result["JWT_USER_ID"] = idMatch?.groupValues?.get(1) ?: ""

Available bindings: context.variables, context.responseBody, context.responseHeaders, context.requestHeaders, context.requestBody. Write output with result["KEY"] = "value".

Trigger in a request's scriptLines:

TOKEN = response.body.accessToken
run:parse-token

After Login, {{script.JWT_USER_ID}} is available everywhere.

6. Secrets — Encrypted Local Credentials

API keys, tokens, and passwords don't belong in plain JSON or in your Git history. Synapse keeps them in an encrypted, machine-local vault that lives outside your repository, so they never appear in your collections or anything an AI agent can read.

Import from a .env file (once)

Click the 🔒 Secrets icon in the toolbar (next to ⚙ Settings) → Import .env, and select your .env file:

API_KEY=sk-live-abc123
DB_PASSWORD=hunter2
WEBHOOK_SECRET=whsec_xyz

You only need to do this once per machine. The .env file is not copied into your space or repository — Synapse reads it, encrypts each value, and stores the result in its own local config folder (next to config.json, outside the repo). Keep the original .env file safe and outside your repository.

Use them in any request

Reference a secret with the {{secrets.KEY}} template — anywhere templates work (url, headers, queryParams, body):

{
  "headers": {
    "Authorization": "Bearer {{secrets.API_KEY}}"
  }
}

At send time Synapse decrypts the value on the fly and injects it.

How the encryption works

Hiding secrets in responses

In the Response/Request viewer, a Hide secrets checkbox sits next to Copy (on by default). While it's on, any resolved secret value is shown — and copied — as its {{secrets.KEY}} placeholder instead of the real value. Untick it to reveal and copy the actual values when you need them.

7. Tips & Recipes

Chain requests — automatic token passing

Add scriptLines to Login → send once → every request uses {{script.TOKEN}} in its Authorization header — no copy-pasting.

Switch environments or identities instantly

Put URLs in an environment selector, credentials in a credentials selector. Flip the dropdown — the whole workspace retargets.

Control sidebar order

Prefix filenames: 01-login.json, 02-current-user.json. Folders work the same way.

Keep secrets safe

Import sensitive values via the 🔒 Secrets dialog instead of hardcoding them. They're encrypted with a machine-local key and stored outside your repository — nothing is tracked in Git. Import your .env once per machine, keep the original file outside the repo, and reference values with {{secrets.KEY}}.

Let an AI write your collections

Every file is structured JSON in a predictable path. Tell any LLM what API you need and drop the output into collections/ and selectors/ — your secrets stay encrypted and out of reach.

Combine templates freely

Templates resolve at send time and can be mixed in any string field:

{{selector.environment.BASE_URL}}/products/{{selector.product}}?ts={{script.timestamp()}}