{"openapi":"3.1.0","info":{"title":"sōtem connect API","version":"1.0.0","description":"Connect your own system to sōtem. Send records (people, companies, deals and your own record types), read them back, start agents, see approvals, and send signed webhooks. Every call uses a workspace API key made for one connection in Connections > Connect your own system."},"servers":[{"url":"https://api.mondaily.com"}],"security":[{"apiKey":[]}],"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"A workspace key (md_live_...) made for the connection, with the scopes it needs."},"signature":{"type":"apiKey","in":"header","name":"X-Mondaily-Signature","description":"t=<unix seconds>,v1=<hex HMAC-SHA256 of \"<t>.<raw body>\" with the connection's webhook secret>. At most 5 minutes old; each signed delivery is accepted once."}},"schemas":{"Error":{"type":"object","properties":{"error":{"type":"string"},"code":{"type":"string"}},"required":["error"]},"Record":{"type":"object","required":["object_type","id"],"properties":{"object_type":{"type":"string","pattern":"^[a-z][a-z0-9_]{0,62}$","description":"people, companies, deals, or one of your workspace's own record types."},"id":{"type":"string","pattern":"^[A-Za-z0-9._:@/+=#~-]{1,200}$","description":"Your own id for the record. Sending the same id again updates the same record."},"fields":{"type":"object","additionalProperties":{"oneOf":[{"type":"string"},{"type":"number"},{"type":"boolean"},{"type":"null"},{"type":"array","items":{"oneOf":[{"type":"string"},{"type":"number"}]}}]},"description":"Field names in lower case with underscores. When the connection has a mapping for this type, use your own names and the mapping applies."},"updated_at":{"type":"string","description":"When it last changed in your system (ISO 8601 or a unix time)."},"deleted":{"type":"boolean","description":"Deleted in your system. The record in sōtem is kept and marked, never removed."}}},"RecordResult":{"type":"object","properties":{"id":{"type":"string"},"object_type":{"type":"string"},"outcome":{"type":"string","enum":["created","updated","linked","unchanged","skipped_deleted","marked_deleted","refused"]},"node_id":{"type":["string","null"]},"reason":{"type":"string"},"dropped":{"type":"array","items":{"type":"string"}}}}}},"paths":{"/api/v1/connect/records":{"post":{"summary":"Add or update records","description":"Up to 100 records per call, matched by your id. A field someone changed in sōtem since your last send is kept, and both values are recorded for review. People, companies and deals are matched to records the workspace already has (email, domain, name) before a new one is made. Send an Idempotency-Key header to make a retried call safe: the same key returns the first answer.","security":[{"apiKey":[]}],"x-scope":"records:write","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{1,120}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["records"],"properties":{"records":{"type":"array","maxItems":100,"items":{"$ref":"#/components/schemas/Record"}}}}}}},"responses":{"200":{"description":"Each record with its outcome","content":{"application/json":{"schema":{"type":"object","properties":{"results":{"type":"array","items":{"$ref":"#/components/schemas/RecordResult"}},"totals":{"type":"object"},"replayed":{"type":"boolean"}}}}}},"400":{"description":"The body is not a list of records","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Missing or invalid key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"The key lacks records:write, or the connection does not accept sends","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"The key belongs to no connection, or the connection is paused","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Over the key's requests a minute","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"The server is not set up for connections yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"summary":"Read records this connection holds","security":[{"apiKey":[]}],"x-scope":"records:read","parameters":[{"name":"object_type","in":"query","required":false,"schema":{"type":"string"}},{"name":"id","in":"query","required":false,"schema":{"type":"string"},"description":"Your own id"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100}},{"name":"after","in":"query","required":false,"schema":{"type":"string"},"description":"The next value from the previous page"}],"responses":{"200":{"description":"Records with their fields as they are in sōtem now"},"403":{"description":"The key lacks records:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/connect/hooks/{connectionId}":{"post":{"summary":"Signed webhook from your system","description":"Sign the raw body with the connection's webhook secret. Body: { \"type\": \"records.upsert\", \"records\": [...] } writes records like POST /records; { \"type\": \"sync.requested\", \"object_type\": \"deals\" } asks sōtem to read that type from your API now.","security":[{"signature":[]}],"parameters":[{"name":"connectionId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Accepted"},"401":{"description":"Missing, wrong or expired signature","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such connection","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"This signed delivery was already received","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/connect/agents/{agentId}/run":{"post":{"summary":"Start one of your custom agents","description":"Runs the agent once, like Run now, as the member who made the key (an owner or admin). Anything it would change waits for approval. Limited per agent per day.","security":[{"apiKey":[]}],"x-scope":"agents:run","parameters":[{"name":"agentId","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"The finished run"},"403":{"description":"The key lacks agents:run or its member is not an owner or admin","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Run limit for today reached","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/v1/connect/approvals":{"get":{"summary":"What is waiting for approval","security":[{"apiKey":[]}],"x-scope":"approvals:read","parameters":[{"name":"status","in":"query","required":false,"schema":{"type":"string","enum":["pending","approved","rejected"]}}],"responses":{"200":{"description":"Approval cards the key's member may see: id, title, agent, risk, status, dates"},"403":{"description":"The key lacks approvals:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"agent.finished":{"post":{"summary":"An agent run finished","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"agent.finished"},"created_at":{"type":"string"},"workspace_id":{"type":"string"},"data":{"type":"object","properties":{"run_id":{"type":"string"},"agent":{"type":["string","null"]}}}}}}}},"responses":{"200":{"description":"Any 2xx counts as delivered"}}}},"approval.decided":{"post":{"summary":"Someone approved or rejected a card","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"approval.decided"},"data":{"type":"object","properties":{"decision_id":{"type":"string"},"decision":{"enum":["approved","rejected"]},"agent":{"type":["string","null"]},"kind":{"type":["string","null"]},"by":{"enum":["person","autonomy"]}}}}}}}},"responses":{"200":{"description":"Any 2xx counts as delivered"}}}},"record.changed":{"post":{"summary":"A record was added, changed or deleted in sōtem","requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string"},"type":{"const":"record.changed"},"data":{"type":"object","properties":{"record_id":{"type":"string"},"object_type":{"type":["string","null"]},"change":{"enum":["created","updated","deleted"]}}}}}}}},"responses":{"200":{"description":"Any 2xx counts as delivered"}}}}}}