{
  "openapi": "3.1.0",
  "info": {
    "title": "Fieldproxy REST API",
    "version": "1.0",
    "description": "Read and write a Fieldproxy workspace's data. Every call is a POST with a JSON body to the workspace's regional API base, with an x-api-key header. Keys are created in Settings, Security, API keys with an expiry (24h, 7d, 30d, 90d, 1 year or never), operations (read, insert, update, delete) and an optional table allowlist. Find the base URL with POST https://api.fieldproxy.ai/auth/org {\"orgid\": \"<workspace id>\"} -> settings.url. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset headers. Writes fire the workspace's automations.",
    "contact": {
      "name": "Fieldproxy",
      "url": "https://www.fieldproxy.ai/developers"
    }
  },
  "externalDocs": {
    "url": "https://www.fieldproxy.ai/developers/docs/rest-api"
  },
  "servers": [
    {
      "url": "https://api-india-1.fieldproxy.ai",
      "description": "India"
    },
    {
      "url": "https://api-us-east-1.fieldproxy.ai",
      "description": "US East"
    },
    {
      "url": "https://{apiHost}",
      "description": "Your workspace's regional API host",
      "variables": {
        "apiHost": {
          "default": "api-india-1.fieldproxy.ai"
        }
      }
    }
  ],
  "security": [
    {
      "apiKey": []
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "WriteResult": {
        "type": "object",
        "required": [
          "message",
          "rowCount",
          "table",
          "tenant"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "rowCount": {
            "type": "integer"
          },
          "table": {
            "type": "string"
          },
          "tenant": {
            "type": "string",
            "description": "The workspace id."
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "message"
        ],
        "properties": {
          "message": {
            "type": "string"
          },
          "error": {
            "type": "string",
            "description": "Database error text (read, update and delete failures)."
          },
          "pgCode": {
            "type": "string",
            "description": "Postgres error code (insert failures)."
          },
          "column": {
            "type": "string"
          },
          "detail": {
            "type": "string"
          },
          "note": {
            "type": "string"
          },
          "table": {
            "type": "string"
          },
          "tenant": {
            "type": "string"
          },
          "expectedColumns": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "rowErrors": {
            "type": "array",
            "items": {
              "type": "object"
            }
          }
        }
      }
    }
  },
  "paths": {
    "/api/read": {
      "post": {
        "summary": "Read rows",
        "description": "Returns every row matching condition, all columns. No paging, column selection or sorting; extra keys are ignored.",
        "operationId": "read_rows",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tableName",
                  "condition"
                ],
                "properties": {
                  "tableName": {
                    "type": "string",
                    "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
                    "description": "The table. Must be on the key's table allowlist if it has one."
                  },
                  "condition": {
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    },
                    "description": "Column-value pairs; every pair must match by equality (AND). No operators, lists, patterns or null matching. Must not be empty."
                  }
                }
              },
              "example": {
                "tableName": "your_table",
                "condition": {
                  "id": 1
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Matching rows.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "rowCount",
                    "table",
                    "tenant"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": true,
                        "description": "Column names to values."
                      }
                    },
                    "rowCount": {
                      "type": "integer"
                    },
                    "table": {
                      "type": "string"
                    },
                    "tenant": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (see message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No x-api-key header: {\"message\": \"Authentication required\"}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Unknown key (\"Invalid token\"), revoked key (\"API key has been revoked\"), or table not on the allowlist (\"API key is not authorized for table '<name>'\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unknown column or a value the column cannot hold: {\"message\": \"Read failed\", \"error\": \"...\"}"
          }
        }
      }
    },
    "/api/insert": {
      "post": {
        "summary": "Insert rows",
        "description": "Inserts all rows in one atomic INSERT: if any row fails, none are inserted. Every row must have the same keys as the first. Omitted columns take database defaults. New rows are not returned.",
        "operationId": "insert_rows",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tableName",
                  "data"
                ],
                "properties": {
                  "tableName": {
                    "type": "string",
                    "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
                    "description": "The table. Must be on the key's table allowlist if it has one."
                  },
                  "data": {
                    "type": "array",
                    "minItems": 1,
                    "items": {
                      "type": "object",
                      "additionalProperties": true,
                      "description": "Column names to values."
                    }
                  }
                }
              },
              "example": {
                "tableName": "your_table",
                "data": [
                  {
                    "name": "Gamma",
                    "status": "open",
                    "qty": 1
                  },
                  {
                    "name": "Delta",
                    "status": "closed",
                    "qty": 9
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "\"Successfully inserted N rows into <table>\"",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (see message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No x-api-key header: {\"message\": \"Authentication required\"}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Unknown key (\"Invalid token\"), revoked key (\"API key has been revoked\"), or table not on the allowlist (\"API key is not authorized for table '<name>'\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/update": {
      "post": {
        "summary": "Update rows",
        "description": "Sets data on every row matching condition. No match returns 200 with rowCount 0. Each changed row fires the workspace's automations.",
        "operationId": "update_rows",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tableName",
                  "condition",
                  "data"
                ],
                "properties": {
                  "tableName": {
                    "type": "string",
                    "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
                    "description": "The table. Must be on the key's table allowlist if it has one."
                  },
                  "condition": {
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    },
                    "description": "Column-value pairs; every pair must match by equality (AND). No operators, lists, patterns or null matching. Must not be empty."
                  },
                  "data": {
                    "type": "object",
                    "additionalProperties": true,
                    "description": "Columns to set (one object, not an array).",
                    "minProperties": 1
                  }
                }
              },
              "example": {
                "tableName": "your_table",
                "condition": {
                  "status": "open"
                },
                "data": {
                  "status": "closed",
                  "qty": 7
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "\"Update successful\"",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (see message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No x-api-key header: {\"message\": \"Authentication required\"}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Unknown key (\"Invalid token\"), revoked key (\"API key has been revoked\"), or table not on the allowlist (\"API key is not authorized for table '<name>'\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unknown column or constraint violation: {\"message\": \"Update failed\", \"error\": \"...\"}"
          }
        }
      }
    },
    "/api/delete": {
      "post": {
        "summary": "Delete rows",
        "description": "Deletes every row matching condition. No match returns 200 with rowCount 0.",
        "operationId": "delete_rows",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "tableName",
                  "condition"
                ],
                "properties": {
                  "tableName": {
                    "type": "string",
                    "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$",
                    "description": "The table. Must be on the key's table allowlist if it has one."
                  },
                  "condition": {
                    "type": "object",
                    "minProperties": 1,
                    "additionalProperties": {
                      "type": [
                        "string",
                        "number",
                        "boolean"
                      ]
                    },
                    "description": "Column-value pairs; every pair must match by equality (AND). No operators, lists, patterns or null matching. Must not be empty."
                  }
                }
              },
              "example": {
                "tableName": "your_table",
                "condition": {
                  "id": 2
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "\"Delete successful\"",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/WriteResult"
                }
              }
            }
          },
          "400": {
            "description": "Invalid body (see message).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "401": {
            "description": "No x-api-key header: {\"message\": \"Authentication required\"}",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "403": {
            "description": "Unknown key (\"Invalid token\"), revoked key (\"API key has been revoked\"), or table not on the allowlist (\"API key is not authorized for table '<name>'\").",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "500": {
            "description": "Unknown column: {\"message\": \"Delete failed\", \"error\": \"...\"}"
          }
        }
      }
    }
  }
}