The hierarchy

Most API tools give you a flat list of saved requests. API Craft models an API the way an API actually is: a set of resources, each with operations, that you exercise through request instances.

Project (your repo)
└── API                     (one OpenAPI spec)
    └── Resource            (e.g. Pet)
        └── Operation       (e.g. get, create, delete)
            └── Instance     (a concrete saved request)

The levels

  • Project: the repo. Holds one or more APIs plus project-wide config.
  • API: one service, backed by one imported OpenAPI spec. Has a slug, a base URL, and defaults.
  • Resource: a named group of operations (Pet). Resources are flat, with an optional parent relationship; the app shows them as a tree, but the model underneath is a simple list.
  • Operation: a single endpoint within a resource (Pet.getGET /pet/{petId}). Operations come from the spec, or you can define one locally when the spec doesn't have it.
  • Instance: a concrete request you can run: an operation plus actual parameter values, a body, and auth. One operation can have many instances.

Why not a flat list

A flat list of requests rots. Rename an endpoint and every copy drifts. Onboard someone and they can't tell which of forty requests is canonical. Modeling resources and operations keeps requests anchored to the spec: an instance points at Pet.get, so it stays meaningful as the project grows, and the tooling can tell you when the underlying operation changes.

How it maps to files

Using the Petstore API:

apis/petstore-api/
├── api.json                                  # the API
└── resources/
    └── Pet/                                  # the resource
        ├── _resource.json                    # resource metadata + operation overrides
        └── requests/
            ├── get-pet.json                  # an instance of Pet.get
            └── create-pet.json               # an instance of Pet.create

Operations themselves aren't stored as files; they're derived from the spec by the schema mapping (see OpenAPI as the source of truth). _resource.json only holds the extra metadata you add on top: notes, overrides, locally defined operations.

An instance references its operation:

{
  "version": 2,
  "name": "get-pet",
  "operation": { "resource": "Pet", "name": "get" },
  "params": { "path": { "petId": { "value": "10", "enabled": true } } }
}

A standalone request that doesn't map to a spec operation defines its call inline instead:

{
  "version": 2,
  "name": "quick-inventory-check",
  "operation": { "method": "GET", "url": "{{baseUrl}}/store/inventory" }
}

Next: how the spec and your edits coexist without duplicating anything → OpenAPI as the source of truth.