openapi: 3.0.2 servers: - url: /api security: - {} info: version: 3.18.4 title: GripMock API Schema description: | REST control plane for [GripMock](https://github.com/bavix/gripmock), a gRPC mock server. Use it to load stubs, ask which stub a request would match, read call history and assert call counts — all while the server keeps running. **Base URL.** Every path below is relative to `/api`, served on the HTTP port (`4771` by default). The gRPC port (`4770`) and the ConnectRPC/gRPC-web gateway (`4769`) are separate. **Sessions.** Send `X-Gripmock-Session: ` to scope a request to one session. Stubs created within a session are visible only there, and call history is kept apart. Without the header the request works against the global scope. The header is the only thing that decides scope here: a `session` field inside a posted stub is ignored, so no caller can place stubs into someone else's session. Stub files loaded from disk keep their own `session` field. **Not in this document.** `POST /api/mcp` speaks the Model Context Protocol for agent tooling, and `GET /metrics` — outside `/api` — serves Prometheus metrics. contact: name: Maksim Babichev url: https://github.com/bavix/gripmock-openapi license: name: MIT url: https://github.com/bavix/gripmock-openapi/blob/master/LICENSE tags: - name: healthcheck description: Liveness and readiness probes. - name: dashboard description: Aggregate counters and build/runtime information behind the web UI. - name: sessions description: Session IDs currently known to the server. - name: services description: Services and methods GripMock can serve, across every descriptor source. - name: stubs description: >- Create, list, search and delete stubs, and inspect why one matched. Send `X-Gripmock-Session: ` to scope the call to one session; without it the request works against the global scope. - name: history description: >- Calls the server has answered, newest first. Send `X-Gripmock-Session: ` to scope the call to one session; without it the request works against the global scope. - name: verify description: >- Assert how many times a method was called. Send `X-Gripmock-Session: ` to scope the call to one session; without it the request works against the global scope. - name: descriptors description: Load a compiled `FileDescriptorSet` into a running server. paths: # healthcheck /health/liveness: get: tags: - healthcheck summary: Liveness check description: This endpoint indicates that the service is alive and ready to handle requests operationId: liveness responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/MessageOK' '400': description: Bad Request '500': description: Internal Server Error /health/readiness: get: tags: - healthcheck summary: Readiness check description: The test indicates readiness to receive traffic operationId: readiness responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/MessageOK' '400': description: Bad Request '500': description: Internal Server Error # dashboard /dashboard: get: tags: - dashboard summary: Dashboard aggregate payload description: Returns combined dashboard counters, runtime metadata, and process state in one response. operationId: dashboard responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/Dashboard' '500': description: Internal Server Error /dashboard/overview: get: tags: - dashboard summary: Dashboard overview metrics description: Returns lightweight aggregate counters for admin UI dashboard. operationId: dashboardOverview responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/DashboardOverview' '500': description: Internal Server Error /dashboard/info: get: tags: - dashboard summary: Dashboard runtime and build info description: Returns GripMock build metadata and current runtime process information. operationId: dashboardInfo responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/DashboardInfo' '500': description: Internal Server Error # sessions /sessions: get: tags: - sessions summary: Session options description: Returns distinct non-empty session IDs available in current stubs. operationId: sessionsList responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/Sessions' '500': description: Internal Server Error # services reflection /services: get: tags: - services summary: Services description: List of registered services operationId: servicesList responses: '200': description: Successful operation content: application/json: schema: type: array items: $ref: '#/components/schemas/Service' '404': description: No services found '500': description: Internal Server Error /services/{serviceID}/methods: get: tags: - services summary: Service methods description: List of registered service methods operationId: serviceMethodsList parameters: - name: serviceID in: path description: ID of service required: true schema: type: string responses: '200': description: Successful operation content: application/json: schema: type: array items: $ref: '#/components/schemas/Method' '400': description: Invalid service ID '404': description: Service not found '500': description: Internal Server Error /services/{serviceID}/methods/{methodID}: get: tags: - services summary: Service method details description: Returns exact metadata for one method (by short name or full method id). operationId: serviceMethodGet parameters: - name: serviceID in: path description: Full service name (e.g. helloworld.Greeter) required: true schema: type: string - name: methodID in: path description: Method short name (e.g. SayHello) or full id (e.g. helloworld.Greeter/SayHello) required: true schema: type: string responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/Method' '400': description: Invalid service or method id '404': description: Service or method not found '500': description: Internal Server Error /services/{serviceID}: get: tags: - services summary: Service details description: Returns exact metadata for one service including all methods and streaming capabilities. operationId: serviceGet parameters: - name: serviceID in: path description: Full service name (e.g. helloworld.Greeter) required: true schema: type: string responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/Service' '400': description: Invalid service ID '404': description: Service not found '500': description: Internal Server Error delete: tags: - services summary: Remove service description: Removes a service added via POST /descriptors. Services from startup (proto path) cannot be removed. operationId: deleteService parameters: - name: serviceID in: path description: Full service name (e.g. helloworld.Greeter) required: true schema: type: string responses: '204': description: Service removed successfully '404': description: Service not found (not added via REST or already removed) '500': description: Internal Server Error # stubs /stubs/used: get: tags: - stubs summary: Getting a list of used stubs description: The list is needed to quickly find used stubs operationId: listUsedStubs responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/StubList' '404': description: No used stubs found '500': description: Internal Server Error /stubs/unused: get: tags: - stubs summary: Getting a list of unused stubs description: The list is needed to quickly find unused stubs operationId: listUnusedStubs responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/StubList' '404': description: No unused stubs found '500': description: Internal Server Error /stubs: get: tags: - stubs summary: Getting a list of stubs description: The list of stubs is required to view all added stubs. Use source query param to filter by source. operationId: listStubs parameters: - name: source in: query description: Filter by source (file, rest, mcp, proxy) required: false schema: type: string - name: service in: query description: Filter by service name (exact match) required: false schema: type: string - name: method in: query description: Filter by method name (exact match) required: false schema: type: string - name: session in: query description: Filter by session ID (empty means global stubs) required: false schema: type: string - name: q in: query description: Case-insensitive substring search over service, method and stub ID required: false schema: type: string - name: matcher in: query description: >- Filter by matcher kind(s) present on the stub input. Comma-separated for OR semantics (e.g. "glob,anyOf"). Valid kinds: equals, contains, matches, glob, anyOf. required: false schema: type: string - name: limit in: query description: Maximum number of returned stubs required: false schema: type: integer minimum: 1 - name: offset in: query description: Number of stubs to skip before returning results required: false schema: type: integer minimum: 0 - name: sort in: query description: Sort order for result list required: false schema: type: string responses: '200': description: Successful operation headers: X-Total-Count: description: Total number of stubs matching the filters, before pagination schema: type: integer content: application/json: schema: $ref: '#/components/schemas/StubList' '400': description: >- A query parameter could not be parsed, for example a non-numeric `limit`. '404': description: No stubs found '500': description: Internal Server Error post: tags: - stubs summary: Add a new stub to the store description: Creates a new stub or multiple stubs and adds them to the storage operationId: addStub responses: '200': description: Successful operation content: application/json: schema: oneOf: - $ref: '#/components/schemas/ListID' '400': description: >- The payload is not valid JSON, or the stub failed validation — for example `input` and `inputs` both set, or `output` carrying both the unary side and `stream`. The body holds an `error` string naming the field. '413': description: Payload Too Large '500': description: Internal Server Error requestBody: description: Create a new stub in the store required: true content: application/json: schema: oneOf: - $ref: '#/components/schemas/StubList' - $ref: '#/components/schemas/Stub' delete: tags: - stubs summary: Remove stubs description: >- Deletes stubs. With `X-Gripmock-Session` only the stubs of that session are removed, so one client cannot wipe another session's fixtures; without the header the whole stub storage is cleared. operationId: purgeStubs responses: '204': description: Successful operation '400': description: Bad Request '500': description: Internal Server Error /stubs/batchDelete: post: tags: - stubs summary: Deletes a batch of stubs by IDs description: Takes IDs as input and deletes them operationId: batchStubsDelete responses: '204': description: Successful operation '400': description: Invalid IDs provided '404': description: Some stubs not found '413': description: Payload Too Large '500': description: Internal Server Error requestBody: description: Delete stubs by their IDs required: true content: application/json: schema: $ref: '#/components/schemas/ListID' /stubs/validate: post: tags: - stubs summary: Validate a stub payload without persisting description: Validates one or more stubs and returns them normalized without adding to storage operationId: validateStub responses: '200': description: Successful operation content: application/json: schema: oneOf: - $ref: '#/components/schemas/StubList' '400': description: >- The payload is not valid JSON, or the stub failed validation — for example `input` and `inputs` both set, or `output` carrying both the unary side and `stream`. The body holds an `error` string naming the field. '413': description: Payload Too Large '500': description: Internal Server Error requestBody: description: Stub payload to validate required: true content: application/json: schema: oneOf: - $ref: '#/components/schemas/StubList' - $ref: '#/components/schemas/Stub' /stubs/{uuid}: get: tags: - stubs summary: Get Stub by ID description: Searches for Stub by ID operationId: findByID parameters: - name: uuid in: path description: ID of stub required: true schema: $ref: '#/components/schemas/ID' responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/Stub' '400': description: Invalid UUID format '404': description: Stub not found '500': description: Internal Server Error delete: tags: - stubs summary: Deletes stub by ID description: The method removes the stub by ID operationId: deleteStubByID parameters: - name: uuid in: path description: ID of stub required: true schema: $ref: '#/components/schemas/ID' responses: '204': description: successful operation '400': description: Invalid UUID format '404': description: Stub not found '500': description: Internal Server Error /stubs/search: post: tags: - stubs summary: Stub storage search description: Performs a search for a stub by the given conditions operationId: searchStubs responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/SearchResponse' '400': description: Invalid search criteria '413': description: Payload Too Large '422': description: Validation error '500': description: Internal Server Error requestBody: description: Search criteria including service, method, headers and data to match against stubs required: true content: application/json: schema: $ref: '#/components/schemas/SearchRequest' /stubs/inspect: post: tags: - stubs summary: Inspect stub matching decision path description: Returns detailed matching stages/candidates for a query without consuming stub times. operationId: inspectStubs responses: '200': description: Successful operation content: application/json: schema: $ref: '#/components/schemas/InspectReport' '400': description: Invalid inspect criteria '413': description: Payload Too Large '422': description: Validation error '500': description: Internal Server Error requestBody: description: Inspect criteria including service, method, optional headers/session and input messages required: true content: application/json: schema: $ref: '#/components/schemas/InspectRequest' # history & verify /history: get: tags: - history summary: Get call history description: Returns recorded gRPC calls (when history is enabled) operationId: listHistory parameters: - name: limit in: query required: false description: Return at most N most-recent records schema: type: integer minimum: 0 - name: offset in: query required: false description: Skip the N newest records (page backward through older calls) schema: type: integer minimum: 0 - name: service in: query required: false schema: type: string description: >- Keep only calls to this fully qualified service name. - name: method in: query required: false schema: type: string description: >- Keep only calls to this method name. - name: error in: query required: false description: When true, return only calls that ended with a gRPC error schema: type: boolean responses: '200': description: List of recorded calls headers: X-Total-Count: description: Total number of records before pagination schema: type: integer content: application/json: schema: $ref: '#/components/schemas/HistoryList' '400': description: >- A query parameter could not be parsed, for example a non-numeric `limit`. '500': description: Internal Server Error delete: tags: - history summary: Purge call history description: >- Deletes recorded calls. With `X-Gripmock-Session` only the records of that session are removed, so a test can reset its own history without disturbing the calls of a parallel session; without the header the whole history is cleared. operationId: purgeHistory responses: '200': description: Number of records deleted content: application/json: schema: $ref: '#/components/schemas/HistoryPurged' '500': description: Internal Server Error /verify: post: tags: - verify summary: Verify call counts description: >- Asserts that a method was called a specified number of times. With `X-Gripmock-Session` the count covers that session's calls plus global ones — the same scope its stubs match in. Without the header every call is counted, including calls made under a session. operationId: verifyCalls responses: '200': description: Verification passed content: application/json: schema: $ref: '#/components/schemas/MessageOK' '400': description: Verification failed (wrong call count) content: application/json: schema: $ref: '#/components/schemas/VerifyError' '413': description: Payload Too Large '500': description: Internal Server Error requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/VerifyRequest' # descriptors /descriptors: get: tags: - descriptors summary: List service IDs from REST-added descriptors description: Returns service IDs (e.g. helloworld.Greeter) added via POST /descriptors. Use DELETE /services/{serviceID} to remove. operationId: listDescriptors responses: '200': description: List of removable service IDs content: application/json: schema: $ref: '#/components/schemas/DescriptorServiceIDs' '500': description: Internal Server Error post: tags: - descriptors summary: Upload FileDescriptorSet description: Accepts binary Protocol Buffers FileDescriptorSet. Registers descriptors for dynamic service discovery. Returns service IDs for later removal via DELETE /services/{serviceID}. operationId: addDescriptors requestBody: required: true content: application/octet-stream: schema: type: string format: binary responses: '200': description: Descriptors registered successfully content: application/json: schema: $ref: '#/components/schemas/AddDescriptorsResponse' '400': description: Invalid or empty FileDescriptorSet '413': description: Payload Too Large '500': description: Internal Server Error components: schemas: # health MessageOK: type: object required: - message - time properties: message: type: string x-omitzero: false description: >- Human-readable result of the operation. time: type: string format: date-time x-omitzero: false description: >- Server time when the response was produced (RFC 3339). description: >- Generic acknowledgement. AddDescriptorsResponse: type: object required: - message - time - serviceIDs properties: message: type: string x-omitzero: false description: >- Human-readable result of the upload. time: type: string format: date-time x-omitzero: false description: >- Server time when the response was produced (RFC 3339). serviceIDs: type: array items: type: string description: Service IDs (e.g. helloworld.Greeter) registered. Use DELETE /services/{serviceID} to remove. description: >- Result of registering an uploaded FileDescriptorSet. DescriptorServiceIDs: type: object required: - serviceIDs properties: serviceIDs: type: array items: type: string description: Service IDs added via POST /descriptors # services description: >- Service IDs registered from descriptors uploaded over REST. Service: type: object required: - id - package - name - methods properties: id: type: string x-omitzero: false description: >- Fully qualified service name, used as the path segment in `/services/{serviceID}`. package: type: string x-omitzero: false description: >- Proto package the service is declared in. name: type: string x-omitzero: false description: >- Service name without the package prefix. methods: type: array items: $ref: '#/components/schemas/Method' x-omitzero: false description: >- Methods the service exposes. description: >- A gRPC service GripMock can serve. Method: type: object required: - id - name - methodType properties: id: type: string x-omitzero: false description: >- Method name, used as the path segment in `/methods/{methodID}`. name: type: string x-omitzero: false description: >- Method name as declared in the proto file. methodType: type: string description: gRPC method interaction type enum: - unary - client_streaming - server_streaming - bidi_streaming x-omitzero: false requestType: type: string description: Fully-qualified protobuf request message type responseType: type: string description: Fully-qualified protobuf response message type requestSchema: $ref: '#/components/schemas/ProtoMessageSchema' responseSchema: $ref: '#/components/schemas/ProtoMessageSchema' clientStreaming: type: boolean description: Indicates client-side streaming method x-go-type-skip-optional-pointer: true serverStreaming: type: boolean description: Indicates server-side streaming method x-go-type-skip-optional-pointer: true description: >- A method of a gRPC service. ProtoMessageSchema: type: object required: - typeName - fields properties: typeName: type: string description: Fully-qualified protobuf message type name recursiveRef: type: boolean description: True when schema expansion stopped due to recursive reference x-go-type-skip-optional-pointer: true fields: type: array items: $ref: '#/components/schemas/ProtoFieldSchema' description: >- Fields declared on the message. description: >- Shape of a proto message, as GripMock resolved it from the descriptor. ProtoFieldSchema: type: object required: - name - jsonName - number - kind - cardinality properties: name: type: string description: >- Field name as declared in the proto file (snake_case). jsonName: type: string description: >- Field name in protojson output (camelCase). number: type: integer minimum: 1 description: >- Field number from the proto definition. kind: type: string description: >- Proto kind, for example `string`, `int32`, `message`, `enum`. cardinality: type: string enum: - optional - required - repeated description: >- Whether the field is optional, required or repeated. typeName: type: string description: Referenced protobuf type for message/enum fields oneof: type: string description: Oneof group name if field belongs to oneof enumValues: type: array items: type: string description: >- Allowed value names when `kind` is `enum`. map: type: boolean x-go-type-skip-optional-pointer: true description: >- True when the field is a proto map. mapKeyKind: type: string description: >- Kind of the map key, when `map` is true. mapValueKind: type: string description: >- Kind of the map value, when `map` is true. mapValueTypeName: type: string description: >- Fully qualified type name of the map value, when it is a message or enum. message: $ref: '#/components/schemas/ProtoMessageSchema' mapValueMessage: $ref: '#/components/schemas/ProtoMessageSchema' # stubs description: >- A single field of a proto message. ID: type: string format: uuid x-go-type: uuid.UUID x-go-type-import: name: uuid path: github.com/google/uuid example: 51c50050-ec27-4dae-a583-a32ca71a1dd5 x-omitzero: false description: >- Stub identifier (UUID). ListID: type: array items: $ref: '#/components/schemas/ID' x-omitzero: false description: >- A list of stub UUIDs. StubList: type: array items: $ref: '#/components/schemas/Stub' x-omitzero: false description: >- A list of stubs. SearchRequest: type: object required: - service - method - data properties: id: $ref: '#/components/schemas/ID' service: type: string example: Gripmock x-omitzero: false description: >- Fully qualified gRPC service name. method: type: string example: SayHello x-omitzero: false description: >- gRPC method name. headers: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Request metadata to match against stub `headers`. data: type: object x-go-type: interface{} additionalProperties: true x-omitzero: false description: >- Request body to match against stub `input`. description: >- A synthetic gRPC request. The server resolves it against the loaded stubs and returns the output of the winning stub, without performing the call. SearchResponse: type: object required: - data - error properties: headers: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Response metadata of the matched stub. data: type: object x-go-type: interface{} additionalProperties: true x-omitzero: false description: >- Response body of the matched stub. error: type: string example: Message not found x-omitzero: false description: >- gRPC status message, empty when the stub returns data. code: type: integer format: uint32 x-go-type: codes.Code x-go-type-import: name: codes path: google.golang.org/grpc/codes example: 3 x-go-type-skip-optional-pointer: true description: >- gRPC status code. description: >- Output of the stub that won the match. CallRecord: type: object properties: service: type: string description: >- Fully qualified gRPC service name. method: type: string description: >- gRPC method name. session: type: string description: Session ID (empty = global) stubId: type: string format: uuid x-go-type: uuid.UUID x-go-type-import: name: uuid path: github.com/google/uuid description: Stub identifier timestamp: type: string format: date-time description: >- When the call was received (RFC 3339). requests: type: array description: Request messages; a unary call carries exactly one items: type: object additionalProperties: true responses: type: array description: >- Response messages; a unary call carries exactly one. Usually an object, but a method returning a well-known type directly records the scalar or array it answered with. items: {} responseHeaders: type: object description: Normalized response metadata (header+trailer) the call answered with additionalProperties: type: string x-go-type-skip-optional-pointer: true code: type: integer description: gRPC status code (e.g., 0 for OK, 5 for NotFound) error: type: string description: >- gRPC status message, empty when the call succeeded. elapsedMs: type: integer format: int64 description: Handler duration in milliseconds description: >- One gRPC call the server answered. HistoryList: type: array items: $ref: '#/components/schemas/CallRecord' description: >- A page of recorded calls, newest first. HistoryPurged: type: object required: - deletedCount properties: deletedCount: type: integer description: >- Number of records removed. session: type: string description: >- Session the purge was scoped to, absent when the whole history was cleared. description: >- Result of a history purge. VerifyRequest: type: object required: - service - method - expectedCount properties: service: type: string description: >- Fully qualified gRPC service name. method: type: string description: >- gRPC method name. expectedCount: type: integer minimum: 0 description: >- Number of calls the method must have received. description: >- Expected number of calls to one method. VerifyError: type: object properties: message: type: string description: >- Human-readable summary of the mismatch. expected: type: integer description: >- Count the caller asked for. actual: type: integer description: >- Count actually recorded. description: >- Reported when the recorded count differs from the expectation. InspectRequest: type: object required: - service - method properties: id: $ref: '#/components/schemas/ID' service: type: string description: >- Fully qualified gRPC service name. method: type: string description: >- gRPC method name. session: type: string description: >- Session to resolve against; empty means the global scope. headers: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Request metadata, matched against stub `headers`. input: type: array items: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Request body, matched against stub `input`. description: >- A request to explain: the server reports every stub it considered and why each was kept or dropped. InspectStage: type: object required: - name - before - after - removed properties: name: type: string description: >- Filter applied at this step: service/method, session, times, headers, input, or the method fallback. before: type: integer description: >- Candidates entering the step. after: type: integer description: >- Candidates surviving the step. removed: type: integer description: >- Candidates dropped by the step (`before` minus `after`). description: >- One filtering step, with how many candidates entered and survived it. InspectCandidateEvent: type: object required: - stage - result properties: stage: type: string description: >- Stage the event belongs to. result: type: string description: >- Whether the candidate passed the stage, was dropped, or was selected. reason: type: string description: >- Why, when the candidate was dropped. description: >- What happened to one candidate at one stage. InspectCandidate: type: object required: - id - service - method - session - priority - times - used - specificity - score - visibleBySession - withinTimes - headersMatched - inputMatched - matched - excludedBy - events properties: id: type: string description: >- Stub UUID. service: type: string description: >- Service the stub answers. method: type: string description: >- Method the stub answers. session: type: string description: >- Session the stub belongs to; empty means global. priority: type: integer description: >- The stub `priority` value. times: type: integer description: >- Effective match limit; `0` means unlimited. used: type: integer description: >- How many times the stub has already matched in this session. specificity: type: integer description: >- How narrowly the stub describes the request. Compared first when picking a winner. score: type: number format: double description: >- Match rank plus `priority × 10`. Breaks ties between equally specific stubs. visibleBySession: type: boolean description: >- False when the stub belongs to a different session. withinTimes: type: boolean description: >- False when the stub is exhausted by its `times` limit. headersMatched: type: boolean description: >- Whether the stub `headers` matched the request metadata. inputMatched: type: boolean description: >- Whether the stub `input` matched the request body. matched: type: boolean description: >- True for the single stub that won. excludedBy: type: array items: type: string description: >- Reasons this candidate was ruled out; empty when it survived. events: type: array items: $ref: '#/components/schemas/InspectCandidateEvent' description: >- Per-stage verdicts for this candidate. description: >- A stub the server considered, with the verdict at each stage. InspectReport: type: object required: - service - method - session - matchedStubId - similarStubId - fallbackToMethod - error - stages - candidates properties: service: type: string description: >- Service that was inspected. method: type: string description: >- Method that was inspected. session: type: string description: >- Session the request was resolved against. matchedStubId: type: string description: >- UUID of the winning stub, absent when nothing matched. similarStubId: type: string description: >- Closest non-matching stub, offered as a hint when nothing matched. fallbackToMethod: type: boolean description: >- True when no stub matched the input and the search widened to any stub on the method. error: type: string description: >- Why the request could not be resolved. stages: type: array items: $ref: '#/components/schemas/InspectStage' description: >- How the candidate set narrowed, step by step. candidates: type: array items: $ref: '#/components/schemas/InspectCandidate' description: >- Every stub considered, with its verdict. description: >- Why a request matched — or did not. Stages show how the candidate set narrowed. DashboardOverview: type: object required: - totalServices - totalStubs - usedStubs - unusedStubs - totalSessions - runtimeDescriptors - totalHistory - historyErrors properties: totalServices: type: integer minimum: 0 description: >- Services currently registered, from every descriptor source. totalStubs: type: integer minimum: 0 description: >- Stubs currently in storage. usedStubs: type: integer minimum: 0 description: >- Stubs matched at least once since startup. unusedStubs: type: integer minimum: 0 description: >- Stubs never matched since startup. coveredMethods: type: integer minimum: 0 description: Number of gRPC methods that have at least one stub x-go-type-skip-optional-pointer: true totalMethods: type: integer minimum: 0 description: Total number of gRPC methods across all services x-go-type-skip-optional-pointer: true grpcAddr: type: string description: Native gRPC listen address x-go-type-skip-optional-pointer: true gatewayAddr: type: string description: ConnectRPC + gRPC-web listen address x-go-type-skip-optional-pointer: true httpAddr: type: string description: Admin REST API + UI listen address x-go-type-skip-optional-pointer: true totalSessions: type: integer minimum: 0 description: >- Sessions currently known to the server. runtimeDescriptors: type: integer minimum: 0 description: >- Descriptors uploaded over REST since startup. totalHistory: type: integer minimum: 0 description: >- Calls recorded in history. historyErrors: type: integer minimum: 0 description: >- Recorded calls that ended in a gRPC error. description: >- Aggregate counters shown on the dashboard. Sessions: type: object required: - sessions properties: sessions: type: array items: type: string description: >- Known session IDs. description: >- Session IDs currently known to the server. DashboardInfo: type: object required: - appName - version - goVersion - compiler - goos - goarch - numCPU - startedAt - uptimeSeconds - ready - historyEnabled - totalServices - totalStubs - totalSessions - runtimeDescriptors properties: appName: type: string description: >- Application name reported by the binary. version: type: string description: >- GripMock version. goVersion: type: string description: >- Go version the binary was built with. compiler: type: string description: >- Go compiler used for the build. goos: type: string description: >- Operating system the binary targets. goarch: type: string description: >- CPU architecture the binary targets. numCPU: type: integer minimum: 1 description: >- CPUs visible to the process. startedAt: type: string format: date-time description: >- When the process started (RFC 3339). uptimeSeconds: type: integer minimum: 0 description: >- Seconds since startup. ready: type: boolean description: >- Whether the server has finished loading and is answering calls. historyEnabled: type: boolean description: >- Whether call history recording is on (`HISTORY_ENABLED`). totalServices: type: integer minimum: 0 description: >- Services currently registered, from every descriptor source. totalStubs: type: integer minimum: 0 description: >- Stubs currently in storage. totalSessions: type: integer minimum: 0 description: >- Sessions currently known to the server. runtimeDescriptors: type: integer minimum: 0 description: >- Descriptors uploaded over REST since startup. description: >- Build and runtime information about this instance. Dashboard: type: object required: - appName - version - goVersion - compiler - goos - goarch - numCPU - startedAt - uptimeSeconds - ready - historyEnabled - totalServices - totalStubs - usedStubs - unusedStubs - totalSessions - runtimeDescriptors - totalHistory - historyErrors properties: appName: type: string description: >- Application name reported by the binary. version: type: string description: >- GripMock version. goVersion: type: string description: >- Go version the binary was built with. compiler: type: string description: >- Go compiler used for the build. goos: type: string description: >- Operating system the binary targets. goarch: type: string description: >- CPU architecture the binary targets. numCPU: type: integer minimum: 1 description: >- CPUs visible to the process. startedAt: type: string format: date-time description: >- When the process started (RFC 3339). uptimeSeconds: type: integer minimum: 0 description: >- Seconds since startup. ready: type: boolean description: >- Whether the server has finished loading and is answering calls. historyEnabled: type: boolean description: >- Whether call history recording is on (`HISTORY_ENABLED`). totalServices: type: integer minimum: 0 description: >- Services currently registered, from every descriptor source. totalStubs: type: integer minimum: 0 description: >- Stubs currently in storage. usedStubs: type: integer minimum: 0 description: >- Stubs matched at least once since startup. unusedStubs: type: integer minimum: 0 description: >- Stubs never matched since startup. coveredMethods: type: integer minimum: 0 description: Number of gRPC methods that have at least one stub x-go-type-skip-optional-pointer: true totalMethods: type: integer minimum: 0 description: Total number of gRPC methods across all services x-go-type-skip-optional-pointer: true grpcAddr: type: string description: Native gRPC listen address x-go-type-skip-optional-pointer: true gatewayAddr: type: string description: ConnectRPC + gRPC-web listen address x-go-type-skip-optional-pointer: true httpAddr: type: string description: Admin REST API + UI listen address x-go-type-skip-optional-pointer: true totalSessions: type: integer minimum: 0 description: >- Sessions currently known to the server. runtimeDescriptors: type: integer minimum: 0 description: >- Descriptors uploaded over REST since startup. totalHistory: type: integer minimum: 0 description: >- Calls recorded in history. historyErrors: type: integer minimum: 0 description: >- Recorded calls that ended in a gRPC error. description: >- Overview and runtime info in a single payload. Stub: type: object required: - service - method - input - output properties: id: $ref: '#/components/schemas/ID' service: type: string example: Gripmock x-omitzero: false description: >- Fully qualified gRPC service name. method: type: string example: SayHello x-omitzero: false description: >- gRPC method name, without the service prefix. priority: type: integer default: 0 description: >- Tie-breaker among equally specific stubs; higher wins. Specificity is compared first, so an `equals` stub still beats a `contains` stub with a higher priority. x-go-type-skip-optional-pointer: true used: type: boolean description: Response-only — whether the stub has matched at least once. Ignored on input. x-go-type-skip-optional-pointer: true session: type: string readOnly: true description: >- Session the stub belongs to; empty means global. Assigned from the `X-Gripmock-Session` request header — a value sent in the body is discarded. x-go-type-skip-optional-pointer: true headers: $ref: '#/components/schemas/StubHeaders' input: $ref: '#/components/schemas/StubInput' x-omitzero: false description: >- Matchers for a unary request body. Mutually exclusive with `inputs`. inputs: type: array description: >- Per-message matchers for client and bidirectional streaming. With one element it is a broadcast pattern that every message must match; with several, element N is matched against the Nth message and the counts must be equal. Mutually exclusive with `input` — a stub with both is rejected. For OR semantics use `input.anyOf`. items: $ref: '#/components/schemas/StubInput' x-go-type-skip-optional-pointer: true output: $ref: '#/components/schemas/StubOutput' x-omitzero: false options: $ref: '#/components/schemas/StubOptions' x-omitzero: true effects: type: array description: Side effects applied after successful stub match items: $ref: '#/components/schemas/StubEffect' x-go-type-skip-optional-pointer: true source: type: string description: Source of the stub (file, rest, mcp, proxy) readOnly: true x-omitzero: true description: >- A single stub: which method it answers, which requests it accepts, and what it returns. StubOptions: type: object description: Optional behavior settings for a stub properties: times: type: integer description: >- Maximum number of matches; `0` means unlimited. Once the limit is reached the stub is exhausted and stops matching, though it stays in storage. minimum: 0 default: 0 x-go-type-skip-optional-pointer: true StubEffect: type: object required: - action properties: action: type: string enum: [upsert, delete] description: >- `upsert` creates or replaces a stub, `delete` removes one. id: type: string description: >- Target stub UUID for `delete`. May be a template that renders to a UUID. x-go-type-skip-optional-pointer: true stub: type: object additionalProperties: true description: >- Stub payload for `upsert`, validated after template rendering. x-go-type-skip-optional-pointer: true description: >- Side effect applied after this stub matches — used to build multi-step flows where one call arms the next. StubInput: type: object properties: ignoreArrayOrder: type: boolean default: false x-go-type-skip-optional-pointer: true description: >- Compare arrays as sets rather than ordered sequences. Applies to this matcher block only — it is not inherited by `anyOf` elements. equals: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Exact match. Every listed field must be present in the request with exactly this value, case-sensitive. Arrays compare in order unless `ignoreArrayOrder` is set. contains: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Subset match. The request must carry at least these fields. Strings match on substring, arrays on containment, nested objects recursively. Extra fields in the request are ignored. matches: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Regex match. Each leaf value is a Go regular expression applied to the corresponding request value. glob: type: object description: >- Glob match. Each leaf value is a shell-style pattern (`*`, `?`, `[...]`) evaluated with Go `path.Match`; `*` does not cross `/`. additionalProperties: true x-go-type-skip-optional-pointer: true anyOf: type: array description: >- Alternative matchers (OR). The stub matches when the blocks above pass AND at least one element here passes. Depth is exactly one — an element cannot itself contain `anyOf`. items: $ref: '#/components/schemas/StubInputAnyOfElement' x-go-type-skip-optional-pointer: true description: >- Matchers applied to the request body. All blocks present are AND-ed; an omitted or empty block always passes, so a stub with every block empty matches any request. StubInputAnyOfElement: type: object properties: ignoreArrayOrder: type: boolean default: false x-go-type-skip-optional-pointer: true description: >- Compare arrays as sets rather than ordered sequences. Applies to this matcher block only — it is not inherited by `anyOf` elements. equals: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Exact match. Every listed field must be present in the request with exactly this value, case-sensitive. Arrays compare in order unless `ignoreArrayOrder` is set. contains: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Subset match. The request must carry at least these fields. Strings match on substring, arrays on containment, nested objects recursively. Extra fields in the request are ignored. matches: type: object additionalProperties: true x-go-type-skip-optional-pointer: true description: >- Regex match. Each leaf value is a Go regular expression applied to the corresponding request value. glob: type: object description: >- Glob match. Each leaf value is a shell-style pattern (`*`, `?`, `[...]`) evaluated with Go `path.Match`; `*` does not cross `/`. additionalProperties: true x-go-type-skip-optional-pointer: true description: >- One alternative of an `anyOf`. Its own blocks are AND-ed together. StubHeaders: type: object x-go-type-skip-optional-pointer: true properties: equals: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Exact match on header values (multiple values are joined with `;`). contains: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Subset match. The request must carry at least these header names; values match on substring. matches: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Regex match on header values. glob: type: object description: >- Glob match on header values, using Go `path.Match`. additionalProperties: type: string x-go-type-skip-optional-pointer: true anyOf: type: array description: >- Alternative header matchers (OR). The stub matches when the blocks above pass AND at least one element here passes. items: $ref: '#/components/schemas/StubHeadersAnyOfElement' x-go-type-skip-optional-pointer: true description: >- Matchers applied to gRPC request metadata. Header names are case-insensitive. All blocks present are AND-ed; an omitted or empty block always passes. StubHeadersAnyOfElement: type: object properties: equals: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Exact match on header values (multiple values are joined with `;`). contains: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Subset match. The request must carry at least these header names; values match on substring. matches: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Regex match on header values. glob: type: object description: >- Glob match on header values, using Go `path.Match`. additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- One alternative of a header `anyOf`. Its own blocks are AND-ed together. StubOutput: type: object allOf: - if: required: [template] properties: template: const: true then: oneOf: - required: [data] properties: data: type: string minLength: 1 not: required: [stream] - required: [stream] properties: stream: type: string minLength: 1 not: required: [data] else: properties: stream: type: array - not: required: [data, stream] properties: data: x-go-type-skip-optional-pointer: true description: >- Response body for unary and client-streaming calls. Usually an object matching the proto message; may be a scalar when the method returns a well-known type directly. stream: x-go-type-skip-optional-pointer: true description: >- Response messages for server and bidirectional streaming, sent in order. May be combined with `error`, `code` and `details`; cannot be combined with `data`. With `template: true` this holds the template text instead of the messages. template: type: boolean x-go-type-skip-optional-pointer: true description: >- Marks `data` or `stream` as a Go template rendered per request. The template in `data` answers with one message and must print exactly one JSON value; the template in `stream` answers with a stream and may print any number of values, or a single array of messages. headers: type: object additionalProperties: type: string x-go-type-skip-optional-pointer: true description: >- Response metadata. trailers: type: object description: >- Trailing metadata, sent after the last message with the status. Independent of `headers`: the same key may appear in both, and each is delivered on its own channel. additionalProperties: type: string x-go-type-skip-optional-pointer: true error: type: string example: Message not found x-go-type-skip-optional-pointer: true description: >- gRPC status message. Returned instead of `data`, and counts as the unary side of the data/stream choice. code: type: integer format: uint32 x-go-type: codes.Code x-go-type-import: name: codes path: google.golang.org/grpc/codes example: 3 x-go-type-skip-optional-pointer: true description: >- gRPC status code; `0` (OK) is the default. details: type: array description: gRPC status details packed into google.protobuf.Any (each item must contain type URL in `type`) items: type: object required: [type] properties: type: type: string description: Full Any type URL (for example, type.googleapis.com/google.rpc.ErrorInfo) additionalProperties: true x-go-type-skip-optional-pointer: true delay: type: string x-go-type: gptypes.Delay x-go-type-import: name: gptypes path: github.com/bavix/gripmock/v3/internal/infra/types description: Delay before sending the response. A Go duration, or a template rendering one. example: "1s" x-omitzero: true x-go-type-skip-optional-pointer: true description: >- What the stub returns. Over this API exactly one side must be set: either the unary side (`data`, `error`, `code`, `details`) or `stream`. A stub carrying both is rejected with `400`.