{
 "openapi": "3.1.0",
 "info": {
  "title": "Haroshemt API",
  "version": "1.1.0",
  "description": "Calls, transcriptions and summaries for your Haroshemt account.\n\nAuthenticate every request with your API key in the `x-api-key` header.\n\n**Getting call data:** Haro pushes each call to your webhook URL as it progresses\n(see the *Webhooks* section below), and `GET /api/v1/call/{call_id}` returns the\ncurrent state of any call whenever you ask."
 },
 "tags": [
  {
   "name": "User",
   "description": "Your account."
  },
  {
   "name": "Customer",
   "description": "Contacts on your account."
  },
  {
   "name": "Call",
   "description": "Recorded calls, with their transcription and summaries."
  }
 ],
 "webhooks": {
  "callUpdate": {
   "post": {
    "summary": "Call update",
    "description": "Haro POSTs a JSON `ApiCall` snapshot to the webhook URL configured on your account,\nonce per event in a call's life. Every payload carries the full current state of the\ncall, so you never need to merge - the latest one wins. Read `call_id` from it and, if\nyou want the state later, `GET /api/v1/call/{call_id}`.\n\n**Events, in the order they happen:**\n\n| # | When | What is new in the payload |\n|---|---|---|\n| 1 | The call ends | `status`, `duration`, `is_missed`, the numbers and the time. No text yet. |\n| 2 | The transcription is ready - usually within a minute | `transcription` |\n| 3 | A summary is ready - a minute or two after the transcription | `detailed_summary` and/or `summary` (see below) |\n\nA call always produces events 1 and 2 (a missed or unanswered call has no transcription\nand stops at 1). Event 3 arrives once per summary that gets produced, so a call can\ntrigger it twice, once or not at all.\n\n**The two summaries:**\n\n- `detailed_summary` - the **auto summary**: a narrative of what was said, produced\n  automatically for every real conversation. Very short calls (roughly under 30 seconds of\n  speech) and missed calls are not summarized. Also produced when the user asks for a\n  summary of a call in the app.\n- `summary` - **task extraction**: the action items from the call, produced when the user\n  says their trigger word (by default \"רשמתי\") during the call, or asks for tasks in the app.\n\n**Delivery:** one POST per event, `Content-Type: application/json`, no retries. Respond\nwith any 2xx quickly; do your processing after you have responded. Deliveries are logged\non our side with your response status, so a failing endpoint can be diagnosed.\n\n**Ordering:** events are sent as they happen and normally arrive in order, but treat each\npayload as the whole truth rather than as a delta - a late event 2 must not overwrite a\nsummary you already have from event 3; the payload of event 3 contains the transcription too.",
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApiCall"
       }
      }
     }
    },
    "responses": {
     "2XX": {
      "description": "Received. Any 2xx is treated as delivered."
     }
    }
   }
  }
 },
 "components": {
  "securitySchemes": {
   "ApiKeyAuth": {
    "type": "apiKey",
    "in": "header",
    "name": "x-api-key"
   }
  },
  "schemas": {
   "User": {
    "type": "object",
    "description": "Public authenticated-user profile returned by GET /api/v1/me.",
    "properties": {
     "id": {
      "type": "string",
      "format": "uuid",
      "description": "User UUID (`users.id`)."
     },
     "name": {
      "type": "string",
      "nullable": true,
      "description": "Display name."
     },
     "phone_number": {
      "type": "string",
      "nullable": true,
      "description": "Primary phone number (E.164 when available)."
     },
     "recorder_phone_number": {
      "type": "string",
      "nullable": true,
      "description": "Recorder / secondary phone number, if configured."
     },
     "user_status": {
      "type": "string",
      "nullable": true,
      "description": "Account status (e.g. active)."
     }
    }
   },
   "ApiCustomer": {
    "type": "object",
    "required": [
     "Name",
     "Phone"
    ],
    "properties": {
     "Name": {
      "type": "string",
      "description": "The customer's name."
     },
     "Phone": {
      "type": "string",
      "description": "The customer's phone number."
     },
     "Notes": {
      "type": "string",
      "description": "Optional notes about the customer."
     },
     "name_prefix": {
      "type": "string",
      "description": "Optional prefix for the customer's name."
     }
    }
   },
   "CustomerIdResponse": {
    "type": "object",
    "properties": {
     "customerId": {
      "type": "string",
      "description": "GCP Postgres customer UUID (found or created)."
     }
    }
   },
   "ApiCall": {
    "type": "object",
    "description": "Public call object. Returned by GET /api/v1/call/{call_id} and POSTed to user webhook URLs.\nIdentify calls with `call_id` only (`calls.id` UUID). Provider IDs are internal and not exposed.\n",
    "properties": {
     "call_id": {
      "type": "string",
      "format": "uuid",
      "description": "Unique call ID (`calls.id`). Use this to fetch call details via GET /api/v1/call/{call_id}."
     },
     "user_id": {
      "type": "string",
      "format": "uuid",
      "description": "Owning user ID (`users.id`)."
     },
     "transcription": {
      "type": "string",
      "description": "The transcription of the call."
     },
     "summary": {
      "type": "string",
      "description": "Task extraction - the action items from the call. Produced when the user says their\ntrigger word (by default \"רשמתי\") during the call, or asks for tasks in the app.\n"
     },
     "detailed_summary": {
      "type": "string",
      "description": "Auto summary - a narrative of what was said. Produced automatically for every real\nconversation, a minute or two after the transcription; very short and missed calls are\nnot summarized. A call can carry either summary, both, or neither. See *Webhooks*.\n"
     },
     "status": {
      "type": "string",
      "description": "The status of the call.",
      "enum": [
       "Ringing",
       "Ended",
       "Answered"
      ]
     },
     "number_from": {
      "type": "string",
      "description": "The calling phone number."
     },
     "number_to": {
      "type": "string",
      "description": "The receiving phone number."
     },
     "date": {
      "type": "string",
      "format": "date-time",
      "description": "The date and time of the call."
     },
     "duration": {
      "type": "number",
      "description": "The duration of the call in seconds."
     },
     "is_missed": {
      "type": "boolean",
      "description": "Whether the call was missed."
     }
    }
   }
  }
 },
 "security": [
  {
   "ApiKeyAuth": []
  }
 ],
 "paths": {
  "/api/v1/me": {
   "get": {
    "summary": "Get authenticated user details",
    "description": "Returns a filtered public profile for the user identified by `x-api-key`.",
    "tags": [
     "User"
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "responses": {
     "200": {
      "description": "Public user profile.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/User"
        },
        "example": {
         "id": "00000000-0000-4000-8000-000000000001",
         "name": "Example User",
         "phone_number": "+972500000000",
         "recorder_phone_number": null,
         "user_status": "active"
        }
       }
      }
     },
     "401": {
      "description": "Unauthorized - `x-api-key` header missing."
     },
     "404": {
      "description": "No user found for the provided API key."
     },
     "500": {
      "description": "Internal server error."
     }
    }
   }
  },
  "/api/v1/customer": {
   "post": {
    "summary": "Find or create a customer",
    "tags": [
     "Customer"
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "requestBody": {
     "required": true,
     "content": {
      "application/json": {
       "schema": {
        "$ref": "#/components/schemas/ApiCustomer"
       }
      }
     }
    },
    "responses": {
     "200": {
      "description": "Customer found or created successfully.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/CustomerIdResponse"
        }
       }
      }
     },
     "401": {
      "description": "Unauthorized - API key missing or invalid."
     },
     "500": {
      "description": "Internal server error or failed to process customer."
     }
    }
   }
  },
  "/api/v1/call/{call_id}": {
   "get": {
    "summary": "Get call details by call ID",
    "description": "Retrieve a call by its `call_id` (GCP `calls.id` UUID).\nUse the same `call_id` delivered in the user webhook `ApiCall` payload.\n",
    "tags": [
     "Call"
    ],
    "security": [
     {
      "ApiKeyAuth": []
     }
    ],
    "parameters": [
     {
      "in": "path",
      "name": "call_id",
      "schema": {
       "type": "string",
       "format": "uuid"
      },
      "required": true,
      "description": "Call UUID from the webhook payload (`ApiCall.call_id` = `calls.id`)."
     }
    ],
    "responses": {
     "200": {
      "description": "Call details fetched successfully.",
      "content": {
       "application/json": {
        "schema": {
         "$ref": "#/components/schemas/ApiCall"
        }
       }
      }
     },
     "400": {
      "description": "Missing call_id path parameter."
     },
     "401": {
      "description": "Unauthorized - `x-api-key` header missing."
     },
     "404": {
      "description": "Call not found for this user and call_id (or unknown API key)."
     },
     "500": {
      "description": "Internal server error."
     }
    }
   }
  }
 },
 "servers": [
  {
   "url": "https://api.haro.co.il",
   "description": "Production"
  }
 ]
}