{"openapi":"3.1.0","info":{"title":"Ekvi API","summary":"Cap tables, option plans and dilution for Cyprus companies, as an event ledger.","description":"The Ekvi API reads and writes a company's share register as an append-only ledger of events. Every\nprojection — the register of members, vesting, option pools, an IFRS 2 schedule — is computed from the\nevents on or before a date, so the same request with the same `as_of` always answers the same.\n\nWrites go through exactly the same capital rules as the portal's forms: an allotment above the authorised\ncapital, a transfer of more shares than the holder has, an exercise above what has vested — each is\nrefused with **409** and the rule's stable name, and nothing is written. A recorded event is never\nedited; a correction is a new event.\n\nAmounts are decimal strings (\"1250.00\"), share counts are integers, dates are ISO (YYYY-MM-DD).\n\n## Authentication\n\nEvery request except `GET /health` carries a bearer token:\n\n    Authorization: Bearer <token>\n\n**Creating a token.** Sign in to the portal, open **Profile → API tokens** (`/app/profile#api-tokens`),\ngive the token a name and confirm with your password (an account without a password confirms by having\nsigned in within the last few minutes). The token is shown once; Ekvi stores only its SHA-256 and cannot\nshow it again. Revoke it on the same page. On an on-prem installation the administrator can also issue\none from the command line: `python -m ekvi.store.admin issue-token <user_id> <label>`.\n\n**What a token may do.** A token acts as the person it belongs to, with that person's role in each\ncompany: an *admin* records events; a *viewer* or *auditor* reads every projection; an *employee* reads\nonly their own rows in the portal and gets 403 from the whole-company endpoints here. Each company is\nisolated twice — by the path and by row-level security in the database — so a token can never read a\ncompany its owner is not a member of (404, which does not say whether the company exists).\n\nA token created on the profile page opens the API only, not the portal, and changing your password\nrevokes it. Keep it like a password.\n\n## Errors\n\n| Status | Body | When |\n|---|---|---|\n| 401 | `ErrorOut` | No Authorization header, a header that is not `Bearer …`, or a token that is unknown, revoked, or belongs to a disabled account. |\n| 403 | `ErrorOut` | Your role in this company does not allow the request (a viewer posting an event, an employee reading the whole register), or the company is archived or read-only. |\n| 404 | `ErrorOut` | The company or fund does not exist or you are not a member of it — deliberately indistinguishable. |\n| 409 | `GuardRefusalOut` | A named capital rule refused the request: `{\"detail\": {\"guard\": \"...\", \"detail\": \"...\"}}`. Branch on `guard`. A duplicate event key is `unique_event_key`. Nothing was recorded. |\n| 413 | `ErrorOut` | The JSON body is larger than the API accepts. |\n| 422 | `ErrorOut or ValidationErrorOut` | The body is not a JSON object, names an unknown event type or field, misses a required field, or a query parameter is not a valid date. |\n| 429 | `ErrorOut` | A daily limit was reached (creating funds). |\n","version":"1.0.0"},"paths":{"/companies":{"get":{"tags":["Companies"],"summary":"List your companies","description":"Every company the token's owner is a member of, with their role in each. Funds are listed separately at GET /funds.","operationId":"list_companies_companies_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CompanyOut"},"title":"Response List Companies Companies Get"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/events":{"get":{"tags":["Ledger"],"summary":"Read the event ledger","description":"Every event recorded for the company, in ledger order, in exactly the shape POST accepts — the ledger is the source of truth and every projection is computed from it. Readers only (admin, viewer, auditor); an employee gets 403.","operationId":"list_events_companies__company_id__events_get","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."}],"responses":{"200":{"description":"Every event of the company in ledger order, each in the shape POST accepts.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true,"oneOf":[{"$ref":"#/components/schemas/Event.ShareClassDefined"},{"$ref":"#/components/schemas/Event.Allotment"},{"$ref":"#/components/schemas/Event.OpeningBalanceRecorded"},{"$ref":"#/components/schemas/Event.Transfer"},{"$ref":"#/components/schemas/Event.Cancellation"},{"$ref":"#/components/schemas/Event.ValuationRecorded"},{"$ref":"#/components/schemas/Event.OptionPlanAdopted"},{"$ref":"#/components/schemas/Event.OptionGranted"},{"$ref":"#/components/schemas/Event.OptionsExercised"},{"$ref":"#/components/schemas/Event.OptionsCancelled"},{"$ref":"#/components/schemas/Event.AuthorizedCapitalIncreased"},{"$ref":"#/components/schemas/Event.AsaSubscribed"},{"$ref":"#/components/schemas/Event.InstrumentConverted"},{"$ref":"#/components/schemas/Event.FundingRoundRecorded"},{"$ref":"#/components/schemas/Event.ConversionRatioAdjusted"},{"$ref":"#/components/schemas/Event.GrantFairValueRecorded"},{"$ref":"#/components/schemas/Event.HolderRecorded"},{"$ref":"#/components/schemas/Event.OwnershipDeclared"}],"discriminator":{"propertyName":"type","mapping":{"ShareClassDefined":"#/components/schemas/Event.ShareClassDefined","Allotment":"#/components/schemas/Event.Allotment","OpeningBalanceRecorded":"#/components/schemas/Event.OpeningBalanceRecorded","Transfer":"#/components/schemas/Event.Transfer","Cancellation":"#/components/schemas/Event.Cancellation","ValuationRecorded":"#/components/schemas/Event.ValuationRecorded","OptionPlanAdopted":"#/components/schemas/Event.OptionPlanAdopted","OptionGranted":"#/components/schemas/Event.OptionGranted","OptionsExercised":"#/components/schemas/Event.OptionsExercised","OptionsCancelled":"#/components/schemas/Event.OptionsCancelled","AuthorizedCapitalIncreased":"#/components/schemas/Event.AuthorizedCapitalIncreased","AsaSubscribed":"#/components/schemas/Event.AsaSubscribed","InstrumentConverted":"#/components/schemas/Event.InstrumentConverted","FundingRoundRecorded":"#/components/schemas/Event.FundingRoundRecorded","ConversionRatioAdjusted":"#/components/schemas/Event.ConversionRatioAdjusted","GrantFairValueRecorded":"#/components/schemas/Event.GrantFairValueRecorded","HolderRecorded":"#/components/schemas/Event.HolderRecorded","OwnershipDeclared":"#/components/schemas/Event.OwnershipDeclared"}}},"title":"Response List Events Companies  Company Id  Events Get"},"example":[{"type":"ShareClassDefined","date":"2025-01-15","class_id":"common","name":"Ordinary","kind":"common","authorized":10000,"nominal_value":"1.00"},{"type":"Allotment","date":"2025-02-01","event_id":"A-2025-01","holder_id":"andreas","class_id":"common","quantity":3500,"price_per_share":"1.00"}]}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Ledger"],"summary":"Record an event","description":"Append one event to the company's ledger. The event is checked against every capital rule — the same guards the portal's forms use — on the register as it stands with this event added; a refusal answers 409 with the rule's name and records nothing. Admins only. Event ids are yours to choose and unique per company, which makes a retry safe: the second POST of the same event answers 409 `unique_event_key` instead of recording it twice.","operationId":"post_event_companies__company_id__events_post","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventRecorded"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"409":{"description":"Refused by a named capital rule; nothing was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuardRefusalOut"}}}},"413":{"description":"The JSON body exceeds the size the API accepts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body is not a valid event: unknown type, unknown or missing field, bad value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"requestBody":{"required":true,"description":"One event. `type` picks the event; the company is the one in the path and is never a field of the body (a body with company_id is refused).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/Event.ShareClassDefined"},{"$ref":"#/components/schemas/Event.Allotment"},{"$ref":"#/components/schemas/Event.OpeningBalanceRecorded"},{"$ref":"#/components/schemas/Event.Transfer"},{"$ref":"#/components/schemas/Event.Cancellation"},{"$ref":"#/components/schemas/Event.ValuationRecorded"},{"$ref":"#/components/schemas/Event.OptionPlanAdopted"},{"$ref":"#/components/schemas/Event.OptionGranted"},{"$ref":"#/components/schemas/Event.OptionsExercised"},{"$ref":"#/components/schemas/Event.OptionsCancelled"},{"$ref":"#/components/schemas/Event.AuthorizedCapitalIncreased"},{"$ref":"#/components/schemas/Event.AsaSubscribed"},{"$ref":"#/components/schemas/Event.InstrumentConverted"},{"$ref":"#/components/schemas/Event.FundingRoundRecorded"},{"$ref":"#/components/schemas/Event.ConversionRatioAdjusted"},{"$ref":"#/components/schemas/Event.GrantFairValueRecorded"},{"$ref":"#/components/schemas/Event.HolderRecorded"},{"$ref":"#/components/schemas/Event.OwnershipDeclared"}],"discriminator":{"propertyName":"type","mapping":{"ShareClassDefined":"#/components/schemas/Event.ShareClassDefined","Allotment":"#/components/schemas/Event.Allotment","OpeningBalanceRecorded":"#/components/schemas/Event.OpeningBalanceRecorded","Transfer":"#/components/schemas/Event.Transfer","Cancellation":"#/components/schemas/Event.Cancellation","ValuationRecorded":"#/components/schemas/Event.ValuationRecorded","OptionPlanAdopted":"#/components/schemas/Event.OptionPlanAdopted","OptionGranted":"#/components/schemas/Event.OptionGranted","OptionsExercised":"#/components/schemas/Event.OptionsExercised","OptionsCancelled":"#/components/schemas/Event.OptionsCancelled","AuthorizedCapitalIncreased":"#/components/schemas/Event.AuthorizedCapitalIncreased","AsaSubscribed":"#/components/schemas/Event.AsaSubscribed","InstrumentConverted":"#/components/schemas/Event.InstrumentConverted","FundingRoundRecorded":"#/components/schemas/Event.FundingRoundRecorded","ConversionRatioAdjusted":"#/components/schemas/Event.ConversionRatioAdjusted","GrantFairValueRecorded":"#/components/schemas/Event.GrantFairValueRecorded","HolderRecorded":"#/components/schemas/Event.HolderRecorded","OwnershipDeclared":"#/components/schemas/Event.OwnershipDeclared"}}},"examples":{"ShareClassDefined":{"summary":"ShareClassDefined","value":{"type":"ShareClassDefined","date":"2025-01-15","class_id":"common","name":"Ordinary","kind":"common","authorized":10000,"nominal_value":"1.00"}},"HolderRecorded":{"summary":"HolderRecorded","value":{"type":"HolderRecorded","date":"2025-01-15","event_id":"h-andreas-1","holder_id":"andreas","kind":"natural_person","legal_name":"Andreas Christofi","capacity":"own_account","address":"12 Makariou Ave, 1065 Nicosia, Cyprus"}},"Allotment":{"summary":"Allotment","value":{"type":"Allotment","date":"2025-02-01","event_id":"A-2025-01","holder_id":"andreas","class_id":"common","quantity":3500,"price_per_share":"1.00"}}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/register":{"get":{"tags":["Projections"],"summary":"Register of members on a date","description":"The register projected from the events on or before `as_of` (default today): one line per holder with shares, options, stakes and the s.105 particulars, plus the instruments (ASAs, convertibles) that are not shares until they convert. Readers only.","operationId":"get_register_companies__company_id__register_get","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Projection date, ISO; defaults to today","title":"As Of"},"description":"Projection date, ISO; defaults to today"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body or a parameter could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/vesting":{"get":{"tags":["Projections"],"summary":"Option vesting on a date","description":"Every option grant with what has vested, been exercised, cancelled or lapsed on `as_of` (default today). Readers only.","operationId":"get_vesting_companies__company_id__vesting_get","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Projection date, ISO; defaults to today","title":"As Of"},"description":"Projection date, ISO; defaults to today"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VestingLineOut"},"title":"Response Get Vesting Companies  Company Id  Vesting Get"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body or a parameter could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/pools":{"get":{"tags":["Projections"],"summary":"Option pools on a date","description":"Each option plan's pool on `as_of` (default today): size, granted, exercised, available. Readers only.","operationId":"get_pools_companies__company_id__pools_get","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Projection date, ISO; defaults to today","title":"As Of"},"description":"Projection date, ISO; defaults to today"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PoolLineOut"},"title":"Response Get Pools Companies  Company Id  Pools Get"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body or a parameter could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/rounds/model":{"post":{"tags":["Modelling"],"summary":"Model a funding round","description":"Model a round on the register at `as_of` (default today): price, pool top-up, instrument conversions, anti-dilution, the dilution table and the events that would make it real. Nothing is recorded, so readers may call it; recording the proposed events is a separate POST /events by an admin. 422 for terms that cannot be read, 409 with the guard name for a round the rules refuse.","operationId":"post_round_model_companies__company_id__rounds_model_post","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."},{"name":"as_of","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Projection date, ISO; defaults to today","title":"As Of"},"description":"Projection date, ISO; defaults to today"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"title":"RoundTerms","description":"A term sheet. Money and prices are decimal strings; unknown keys are refused (422).","properties":{"round_id":{"type":"string","description":"Your id for the round."},"name":{"type":"string"},"kind":{"type":"string","enum":["pre_seed","seed","series_a","series_b","series_c","bridge","convertible","asa"]},"date":{"type":"string","format":"date","description":"Closing date the events would carry."},"pre_money":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$","description":"Pre-money valuation."},"class_id":{"type":"string","description":"Class the new shares are issued in."},"subscriptions":{"type":"array","items":{"type":"object","properties":{"holder_id":{"type":"string"},"amount":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$"}},"required":["holder_id","amount"]}},"new_class":{"type":"object","description":"Define the class in the round (preferred terms).","properties":{"name":{"type":"string"},"authorized":{"type":"integer"},"nominal_value":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$"},"seniority":{"type":"integer"},"liq_multiple":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$"},"anti_dilution":{"type":"string","enum":["none","broad_based","narrow_based","full_ratchet"]},"participating":{"type":"boolean"},"participation_cap":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$"},"conversion_ratio":{"type":"string","pattern":"^[0-9]+(\\.[0-9]+)?$"}},"required":["name","authorized","nominal_value","seniority"]},"pool_top_up":{"type":"object","properties":{"target_pct_fd":{"type":"string","description":"Fraction (\"1/10\") or decimal (\"0.10\")."},"timing":{"type":"string","enum":["pre","post"]},"class_id":{"type":"string"},"plan_id":{"type":"string"},"name":{"type":"string"}},"required":["target_pct_fd","timing","class_id"]},"convert_instruments":{"type":"boolean","description":"Convert outstanding ASAs in the round."},"lead_investor":{"type":"string"},"status":{"type":"string","enum":["planned","open","closed"]}},"required":["round_id","name","kind","date","pre_money","subscriptions","class_id"]},"example":{"round_id":"seed","name":"Seed","kind":"seed","date":"2026-10-12","pre_money":"2000000","class_id":"common","subscriptions":[{"holder_id":"fund-x","amount":"500000"}]}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoundModelOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body is not a valid event: unknown type, unknown or missing field, bad value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"409":{"description":"Refused by a named capital rule; nothing was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuardRefusalOut"}}}}},"security":[{"bearerAuth":[]}]}},"/companies/{company_id}/ifrs2":{"get":{"tags":["Modelling"],"summary":"IFRS 2 expense schedule","description":"The share-based payment expense for the period `from`–`to` (graded-vesting attribution, reversal on forfeiture). Grants without a recorded fair value are listed with their status and left out of the total — never given a guessed value. 409 `guard_period` for an inverted period. Readers only.","operationId":"get_ifrs2_companies__company_id__ifrs2_get","parameters":[{"name":"company_id","in":"path","required":true,"schema":{"type":"string","title":"Company Id"},"description":"The company's id, as GET /companies lists it."},{"name":"from","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Period start, ISO","title":"From"},"description":"Period start, ISO"},{"name":"to","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Period end, ISO","title":"To"},"description":"Period end, ISO"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExpenseReportOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body or a parameter could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}},"409":{"description":"Refused by a named capital rule; nothing was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuardRefusalOut"}}}}},"security":[{"bearerAuth":[]}]}},"/funds":{"get":{"tags":["Funds"],"summary":"List your funds","description":"Every fund the token's owner is a member of, with their role in each.","operationId":"list_funds_funds_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/CompanyOut"},"title":"Response List Funds Funds Get"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Funds"],"summary":"Create a fund","description":"Create a fund; the caller becomes its admin. 403 for an account that may not create one, 429 at the daily limit per user.","operationId":"post_fund_funds_post","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body or a parameter could not be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}},"429":{"description":"A daily limit was reached.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"security":[{"bearerAuth":[]}]}},"/funds/{fund_id}/events":{"get":{"tags":["Funds"],"summary":"Read a fund's ledger","description":"The fund's events the caller may read: the whole ledger for an admin, viewer or auditor; for a limited partner, its own rows and the fund-wide rows partners may see.","operationId":"list_fund_events_funds__fund_id__events_get","parameters":[{"name":"fund_id","in":"path","required":true,"schema":{"type":"string","title":"Fund Id"},"description":"The fund's id, as GET /funds lists it."}],"responses":{"200":{"description":"The fund's events the caller may read, in ledger order.","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response List Fund Events Funds  Fund Id  Events Get"},"example":[{"type":"LpAdmitted","date":"2026-01-10","lp_id":"lp-a","legal_name":"Kyrenia Family Office Ltd","kind":"legal_entity","partner_role":"lp","commitment":"1000000"}]}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationErrorOut"}}}}},"security":[{"bearerAuth":[]}]},"post":{"tags":["Funds"],"summary":"Record a fund event","description":"Record one fund event. A capital call or distribution is written together with one allocation line per partner; 409 with the guard's name for a refusal. Admins only.","operationId":"post_fund_event_funds__fund_id__events_post","parameters":[{"name":"fund_id","in":"path","required":true,"schema":{"type":"string","title":"Fund Id"},"description":"The fund's id, as GET /funds lists it."}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundRecordedOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"409":{"description":"Refused by a named capital rule; nothing was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuardRefusalOut"}}}},"413":{"description":"The JSON body exceeds the size the API accepts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body is not a valid event: unknown type, unknown or missing field, bad value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"requestBody":{"required":true,"description":"One fund event. Allocation lines are written by Ekvi with their header.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/FundEvent.FundConstituted"},{"$ref":"#/components/schemas/FundEvent.LpAdmitted"},{"$ref":"#/components/schemas/FundEvent.CapitalCallIssued"},{"$ref":"#/components/schemas/FundEvent.ContributionReceived"},{"$ref":"#/components/schemas/FundEvent.InvestmentMade"},{"$ref":"#/components/schemas/FundEvent.InvestmentMarked"},{"$ref":"#/components/schemas/FundEvent.InvestmentRealized"},{"$ref":"#/components/schemas/FundEvent.ExpensePaid"},{"$ref":"#/components/schemas/FundEvent.DistributionDeclared"},{"$ref":"#/components/schemas/FundEvent.StatementWithdrawn"}],"discriminator":{"propertyName":"type","mapping":{"FundConstituted":"#/components/schemas/FundEvent.FundConstituted","LpAdmitted":"#/components/schemas/FundEvent.LpAdmitted","CapitalCallIssued":"#/components/schemas/FundEvent.CapitalCallIssued","ContributionReceived":"#/components/schemas/FundEvent.ContributionReceived","InvestmentMade":"#/components/schemas/FundEvent.InvestmentMade","InvestmentMarked":"#/components/schemas/FundEvent.InvestmentMarked","InvestmentRealized":"#/components/schemas/FundEvent.InvestmentRealized","ExpensePaid":"#/components/schemas/FundEvent.ExpensePaid","DistributionDeclared":"#/components/schemas/FundEvent.DistributionDeclared","StatementWithdrawn":"#/components/schemas/FundEvent.StatementWithdrawn"}}},"examples":{"LpAdmitted":{"summary":"LpAdmitted","value":{"type":"LpAdmitted","date":"2026-01-10","lp_id":"lp-a","legal_name":"Kyrenia Family Office Ltd","kind":"legal_entity","partner_role":"lp","commitment":"1000000"}}}}}},"security":[{"bearerAuth":[]}]}},"/funds/{fund_id}/statements":{"post":{"tags":["Funds"],"summary":"Issue a partner statement","description":"Issue a statement on a date with the figures the fund ledger gives: a header and one line per partner. Admins only.","operationId":"post_fund_statement_funds__fund_id__statements_post","parameters":[{"name":"fund_id","in":"path","required":true,"schema":{"type":"string","title":"Fund Id"},"description":"The fund's id, as GET /funds lists it."}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FundRecordedOut"}}}},"401":{"description":"Missing, malformed or invalid bearer token.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"403":{"description":"Your role in this tenant does not allow this request, or the tenant is read-only.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"404":{"description":"No such company/fund, or you are not a member of it (indistinguishable on purpose).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"409":{"description":"Refused by a named capital rule; nothing was recorded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GuardRefusalOut"}}}},"413":{"description":"The JSON body exceeds the size the API accepts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}},"422":{"description":"The body is not a valid event: unknown type, unknown or missing field, bad value.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorOut"}}}}},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatementIn"}}}},"security":[{"bearerAuth":[]}]}},"/health":{"get":{"tags":["Service"],"summary":"Liveness","description":"Answers 200 while the application is up. Needs no token; says nothing about any tenant.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOut"}}}}},"security":[]}}},"components":{"schemas":{"CompanyOut":{"properties":{"id":{"type":"string","title":"Id","description":"Tenant id used in every path, e.g. /companies/{company_id}/register."},"name":{"type":"string","title":"Name","description":"The tenant's name."},"role":{"type":"string","title":"Role","description":"admin | viewer | auditor | employee (company) or lp (fund)."}},"type":"object","required":["id","name","role"],"title":"CompanyOut","description":"A company (or a fund) the caller is a member of, with the caller's role in it.","examples":[{"id":"co-lefkara","name":"Lefkara Robotics Ltd","role":"admin"}]},"ConversionOut":{"properties":{"instrument_id":{"type":"string","title":"Instrument Id","description":"The instrument converting."},"holder_id":{"type":"string","title":"Holder Id","description":"Its holder."},"amount":{"type":"string","title":"Amount","description":"Amount converting, decimal string."},"discount_price":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discount Price","description":"Round price less the discount, if any."},"cap_price":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cap Price","description":"Price at the valuation cap, if any."},"price":{"type":"string","title":"Price","description":"The price applied."},"basis":{"type":"string","title":"Basis","description":"discount | cap | round — which price applied."},"shares":{"type":"integer","title":"Shares","description":"Whole shares issued on conversion."},"paid":{"type":"string","title":"Paid","description":"shares × price, cents."},"remainder":{"type":"string","title":"Remainder","description":"amount − paid."}},"type":"object","required":["instrument_id","holder_id","amount","price","basis","shares","paid","remainder"],"title":"ConversionOut","description":"One instrument converting in a modelled round.","examples":[{"amount":"50000","basis":"discount","cap_price":"800.00","discount_price":"320.00","holder_id":"angel-1","instrument_id":"asa-1","paid":"49920.00","price":"320.00","remainder":"80.00","shares":156}]},"DilutionLineOut":{"properties":{"key":{"type":"string","title":"Key","description":"holder_id or plan_id."},"kind":{"type":"string","title":"Kind","description":"holder | pool."},"before":{"type":"string","title":"Before","description":"As-converted shares + options, exact (\"num/den\" when fractional)."},"after":{"type":"string","title":"After","description":"The same after the round."},"pct_before":{"type":"string","title":"Pct Before","description":"Percent, 4 decimals (display only)."},"pct_after":{"type":"string","title":"Pct After","description":"Percent, 4 decimals (display only)."}},"type":"object","required":["key","kind","before","after","pct_before","pct_after"],"title":"DilutionLineOut","description":"One line of the before/after dilution table.","examples":[{"after":"3500","before":"3500","key":"andreas","kind":"holder","pct_after":"56.0000","pct_before":"70.0000"}]},"ErrorOut":{"properties":{"detail":{"type":"string","title":"Detail","description":"What went wrong, in one sentence."}},"type":"object","required":["detail"],"title":"ErrorOut","description":"The body of every error except a guard refusal: 401, 403, 404, 413, 429 and the 422s Ekvi raises\nitself. `detail` is one English sentence for a person; branch on the status code, not on the text.","examples":[{"detail":"role 'viewer' cannot record events"}]},"Event.Allotment":{"type":"object","title":"Allotment","description":"Issue (allotment) of shares to a holder. price_per_share is the subscription price, not the nominal value.","properties":{"type":{"type":"string","const":"Allotment","enum":["Allotment"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"price_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"round_id":{"type":"string"},"certificate_no":{"type":"string"}},"required":["type","date","event_id","holder_id","class_id","quantity","price_per_share"],"additionalProperties":false},"Event.AsaSubscribed":{"type":"object","title":"AsaSubscribed","description":"Subscription to an advance subscription agreement (the Cyprus SAFE) — an instrument, not shares. Before conversion the holder is not a member: it does not enter the Register of Members, issued or FD (Cap. 113 s.105; position 2 of the 2026-09-18 report). event_id is the instrument's identifier, and InstrumentConverted refers to it.","properties":{"type":{"type":"string","const":"AsaSubscribed","enum":["AsaSubscribed"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"amount":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"discount":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"valuation_cap":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"longstop_date":{"type":"string","format":"date"}},"required":["type","date","event_id","holder_id","amount"],"additionalProperties":false},"Event.AuthorizedCapitalIncreased":{"type":"object","title":"AuthorizedCapitalIncreased","description":"Increase of a class's authorized capital by a general meeting resolution (Cap. 113 s.62). new_authorized is the class's whole new ceiling, not an increment: this way the event reads without arithmetic over history. resolution_date is when the resolution was passed; HE14 (15 days) is counted from it, while date is when the projection starts seeing the new ceiling (usually the same date).","properties":{"type":{"type":"string","const":"AuthorizedCapitalIncreased","enum":["AuthorizedCapitalIncreased"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"new_authorized":{"type":"integer"},"resolution_date":{"type":"string","format":"date"}},"required":["type","date","event_id","class_id","new_authorized","resolution_date"],"additionalProperties":false},"Event.Cancellation":{"type":"object","title":"Cancellation","description":"Cancellation of shares a holder holds in a class: the holding and the issued count go down by quantity. More than the holder holds is refused; reason says why the shares were cancelled.","properties":{"type":{"type":"string","const":"Cancellation","enum":["Cancellation"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"reason":{"type":"string"}},"required":["type","date","event_id","holder_id","class_id","quantity","reason"],"additionalProperties":false},"Event.ConversionRatioAdjusted":{"type":"object","title":"ConversionRatioAdjusted","description":"Anti-dilution: the class's new conversion_ratio after a down round (Ekvi derives it per NVCA: CP2 = CP1 × (A + B) / (A + C) for weighted average, CP2 = round price for full ratchet; ratio = OIP / CP2). new_ratio is the whole new value, not an increment. Adjustments go up only: a ratio below the current one is refused (guard_ratio_not_decreased); cause_round_id must be a recorded round (guard_round_defined).","properties":{"type":{"type":"string","const":"ConversionRatioAdjusted","enum":["ConversionRatioAdjusted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"new_ratio":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"cause_round_id":{"type":"string"},"method":{"type":"string","enum":["broad_based","narrow_based","full_ratchet"]}},"required":["type","date","event_id","class_id","new_ratio","cause_round_id","method"],"additionalProperties":false},"Event.FundingRoundRecorded":{"type":"object","title":"FundingRoundRecorded","description":"A round as a record: an informational event that Allotment.round_id and InstrumentConverted.round_id refer to (a reference to an unrecorded round is refused by guard_round_defined). It issues no shares and changes no holding: price and amounts are deal terms; the issue is separate Allotment events. round_id is the identifier (like class_id of a class); date is when the projection starts seeing the round (usually close_date).","properties":{"type":{"type":"string","const":"FundingRoundRecorded","enum":["FundingRoundRecorded"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"round_id":{"type":"string"},"name":{"type":"string"},"kind":{"type":"string","enum":["pre_seed","seed","series_a","series_b","series_c","bridge","convertible","asa"],"description":"One of the listed values."},"pre_money":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"amount":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"price_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"status":{"type":"string","enum":["planned","open","closed"]},"close_date":{"type":"string","format":"date"},"lead_investor":{"type":"string"}},"required":["type","date","round_id","name","kind","pre_money","amount","price_per_share","status"],"additionalProperties":false},"Event.GrantFairValueRecorded":{"type":"object","title":"GrantFairValueRecorded","description":"IFRS 2: fair value of one option of a grant at grant date (equity-settled: measured once and not remeasured, IFRS 2.10–11), so a second event for the same grant is refused (guard_fair_value_once). method — the model (Black-Scholes, binomial, …), source — who valued it.","properties":{"type":{"type":"string","const":"GrantFairValueRecorded","enum":["GrantFairValueRecorded"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"grant_id":{"type":"string","description":"The OptionGranted event_id."},"fair_value_per_option":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"method":{"type":"string"},"source":{"type":"string"}},"required":["type","date","event_id","grant_id","fair_value_per_option","method"],"additionalProperties":false},"Event.HolderRecorded":{"type":"object","title":"HolderRecorded","description":"The particulars of a holder — the member as an entity behind the opaque `holder_id`.","properties":{"type":{"type":"string","const":"HolderRecorded","enum":["HolderRecorded"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"kind":{"type":"string","enum":["natural_person","legal_entity","joint_holding"],"description":"One of the listed values."},"legal_name":{"type":"string","description":"Name as it goes into the register (Cap. 113 s.105(1)(a))."},"capacity":{"type":"string","enum":["own_account","nominee","trustee","personal_representative"],"description":"In what capacity the holder holds: own_account unless a nominee, trustee or representative."},"address":{"type":"string","description":"Address as it goes into the register (Cap. 113 s.105(1)(a))."},"description":{"type":"string"},"joint_member_ids":{"type":"array","items":{"type":"string"}},"registration_number":{"type":"string"},"incorporation_jurisdiction":{"type":"string"},"is_subsidiary_of_company":{"type":"boolean"},"became_member_while_employed":{"type":"boolean"},"connected_person_s33":{"type":"boolean"},"tax_residency":{"type":"string"},"cy_domiciled":{"type":"boolean"},"reporting_category":{"type":"string","enum":["founder","investor","employee","advisor","other"]},"principal_note":{"type":"string"}},"required":["type","date","event_id","holder_id","kind","legal_name","capacity"],"additionalProperties":false},"Event.InstrumentConverted":{"type":"object","title":"InstrumentConverted","description":"Conversion of an instrument into shares: behaves like an Allotment to the instrument's holder (authorized, nominal value, basis = quantity × price_per_share) and extinguishes the instrument. One instrument converts once. round_id — the round in which the instrument became shares; as for Allotment, a reference to an unrecorded round is refused (guard_round_defined).","properties":{"type":{"type":"string","const":"InstrumentConverted","enum":["InstrumentConverted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"instrument_id":{"type":"string"},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"price_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"certificate_no":{"type":"string"},"round_id":{"type":"string"}},"required":["type","date","event_id","instrument_id","class_id","quantity","price_per_share"],"additionalProperties":false},"Event.OpeningBalanceRecorded":{"type":"object","title":"OpeningBalanceRecorded","description":"A holder's position as it stood on a date, entered without the events that produced it — the first line of a register whose history before that date is not in this ledger (an import of a snapshot: \"Andreas holds 3,500,000 ordinary shares today\").","properties":{"type":{"type":"string","const":"OpeningBalanceRecorded","enum":["OpeningBalanceRecorded"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"consideration_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"certificate_no":{"type":"string"},"source":{"type":"string"}},"required":["type","date","event_id","holder_id","class_id","quantity"],"additionalProperties":false},"Event.OptionGranted":{"type":"object","title":"OptionGranted","description":"A grant of options with vesting terms. vesting_start defaults to the grant date when not given.","properties":{"type":{"type":"string","const":"OptionGranted","enum":["OptionGranted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"plan_id":{"type":"string","description":"The option plan's id (from OptionPlanAdopted)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"strike":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"schedule":{"type":"string","enum":["immediate","monthly","cliff_only"]},"cliff_months":{"type":"integer"},"vesting_months":{"type":"integer"},"vesting_start":{"type":"string","format":"date"},"expiry_date":{"type":"string","format":"date"}},"required":["type","date","event_id","holder_id","plan_id","quantity","strike","schedule","cliff_months","vesting_months"],"additionalProperties":false},"Event.OptionPlanAdopted":{"type":"object","title":"OptionPlanAdopted","description":"Option plan: the pool and the share class issued on exercise. Grants above the pool are refused.","properties":{"type":{"type":"string","const":"OptionPlanAdopted","enum":["OptionPlanAdopted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"plan_id":{"type":"string","description":"The option plan's id (from OptionPlanAdopted)."},"name":{"type":"string"},"pool_size":{"type":"integer"},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."}},"required":["type","date","plan_id","name","pool_size","class_id"],"additionalProperties":false},"Event.OptionsCancelled":{"type":"object","title":"OptionsCancelled","description":"Cancellation (forfeiture) of a grant's unexercised options (leaver, expiry). Above the remainder is refused.","properties":{"type":{"type":"string","const":"OptionsCancelled","enum":["OptionsCancelled"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"grant_id":{"type":"string","description":"The OptionGranted event_id."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"reason":{"type":"string"}},"required":["type","date","event_id","grant_id","quantity","reason"],"additionalProperties":false},"Event.OptionsExercised":{"type":"object","title":"OptionsExercised","description":"Exercise: the grant's holder receives shares of the plan's class. Above vested is refused.","properties":{"type":{"type":"string","const":"OptionsExercised","enum":["OptionsExercised"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"grant_id":{"type":"string","description":"The OptionGranted event_id."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"certificate_no":{"type":"string"}},"required":["type","date","event_id","grant_id","quantity"],"additionalProperties":false},"Event.OwnershipDeclared":{"type":"object","title":"OwnershipDeclared","description":"Who owns a legal-entity holder, as the company was told: one link of the ownership chain the register of beneficial owners is built from (rule cy.ubo.legal_entity_member_requires_look_through).","properties":{"type":{"type":"string","const":"OwnershipDeclared","enum":["OwnershipDeclared"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"holder_id":{"type":"string","description":"The holder's id in this company's ledger (any stable id you choose)."},"owner_id":{"type":"string"},"owner_name":{"type":"string"},"owner_kind":{"type":"string","enum":["natural_person","legal_entity","joint_holding"]},"fraction":{"type":"string","description":"Exact fraction: \"3/5\" or \"0.6\"."},"declared_on":{"type":"string","format":"date"},"source":{"type":"string"}},"required":["type","date","event_id","holder_id","owner_id","owner_name","owner_kind","fraction","declared_on"],"additionalProperties":false},"Event.ShareClassDefined":{"type":"object","title":"ShareClassDefined","description":"A share class and its terms on exit.","properties":{"type":{"type":"string","const":"ShareClassDefined","enum":["ShareClassDefined"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"name":{"type":"string"},"kind":{"type":"string","enum":["common","preferred","option","warrant","convertible","asa"],"description":"One of the listed values."},"authorized":{"type":"integer"},"nominal_value":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"seniority":{"type":"integer"},"liq_multiple":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"anti_dilution":{"type":"string","enum":["none","broad_based","narrow_based","full_ratchet"]},"participating":{"type":"boolean"},"participation_cap":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"conversion_ratio":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"votes_per_share":{"type":"integer"}},"required":["type","date","class_id","name","kind","authorized","nominal_value"],"additionalProperties":false},"Event.Transfer":{"type":"object","title":"Transfer","description":"Transfer of shares between holders. date is the date the transfer is recorded in the Register of Members (the projection changes from it, and HE57 is counted from it too); the execution date of the instrument itself is not modelled (5B).","properties":{"type":{"type":"string","const":"Transfer","enum":["Transfer"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"from_holder_id":{"type":"string"},"to_holder_id":{"type":"string"},"class_id":{"type":"string","description":"The share class's id (from ShareClassDefined)."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"price_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"instrument_ref":{"type":"string"}},"required":["type","date","event_id","from_holder_id","to_holder_id","class_id","quantity","price_per_share"],"additionalProperties":false},"Event.ValuationRecorded":{"type":"object","title":"ValuationRecorded","description":"FMV per share on a date. A grant with no valuation on or before its date is recorded and carries the gap (Register.valuation_on, VestingLine.fmv_at_grant is None); it is not refused.","properties":{"type":{"type":"string","const":"ValuationRecorded","enum":["ValuationRecorded"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"valuation_id":{"type":"string"},"fmv_per_share":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"kind":{"type":"string","enum":["funding_round","board_determined","409a"],"description":"One of the listed values."},"source":{"type":"string"}},"required":["type","date","valuation_id","fmv_per_share","kind"],"additionalProperties":false},"EventRecorded":{"properties":{"seq":{"type":"integer","title":"Seq","description":"Position in the company's ledger; strictly increasing."},"event_type":{"type":"string","title":"Event Type","description":"The event's `type`, e.g. Allotment."},"event_key":{"type":"string","title":"Event Key","description":"The event's unique key within the company (event_id, or class_id / plan_id / valuation_id for definitions). Posting the same key again answers 409 `unique_event_key`."}},"type":"object","required":["seq","event_type","event_key"],"title":"EventRecorded","description":"One event written to the ledger.","examples":[{"event_key":"A-2025-01","event_type":"Allotment","seq":42}]},"ExpenseLineOut":{"properties":{"grant_id":{"type":"string","title":"Grant Id","description":"The grant."},"holder_id":{"type":"string","title":"Holder Id","description":"The grantee."},"plan_id":{"type":"string","title":"Plan Id","description":"The option plan."},"quantity":{"type":"integer","title":"Quantity","description":"Options granted."},"status":{"type":"string","title":"Status","description":"ok | missing_fair_value | no_valuation_on_grant_date."},"fair_value_per_option":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fair Value Per Option","description":"Recorded fair value per option."},"method":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Method","description":"Valuation method recorded with the fair value."},"total_fair_value":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Total Fair Value","description":"quantity × fair value, cents."},"cumulative_start":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cumulative Start","description":"Cumulative expense at the period start."},"cumulative_end":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cumulative End","description":"Cumulative expense at the period end."},"expense":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Expense","description":"Expense recognised in the period."},"reversed":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reversed","description":"Expense reversed in the period (forfeiture)."},"remaining":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Remaining","description":"Fair value not yet recognised."},"forfeited_unvested":{"type":"integer","title":"Forfeited Unvested","description":"Unvested options forfeited in the period."}},"type":"object","required":["grant_id","holder_id","plan_id","quantity","status","forfeited_unvested"],"title":"ExpenseLineOut","description":"One grant in an IFRS 2 expense schedule. Amounts are null on a line that is not measured.","examples":[{"cumulative_end":"190.00","cumulative_start":"100.00","expense":"90.00","fair_value_per_option":"0.90","forfeited_unvested":0,"grant_id":"G-1","holder_id":"eleni","method":"black_scholes","plan_id":"esop-2025","quantity":480,"remaining":"242.00","reversed":"0.00","status":"ok","total_fair_value":"432.00"}]},"ExpenseReportOut":{"properties":{"company_id":{"type":"string","title":"Company Id","description":"The company of the path."},"period_start":{"type":"string","title":"Period Start","description":"ISO."},"period_end":{"type":"string","title":"Period End","description":"ISO."},"complete":{"type":"boolean","title":"Complete","description":"False when any grant could not be measured."},"total_expense":{"type":"string","title":"Total Expense","description":"Over the measured lines only, cents."},"excluded_grants":{"type":"integer","title":"Excluded Grants","description":"Lines not in total_expense (status other than ok)."},"lines":{"items":{"$ref":"#/components/schemas/ExpenseLineOut"},"type":"array","title":"Lines","description":"One line per grant."}},"type":"object","required":["company_id","period_start","period_end","complete","total_expense","excluded_grants","lines"],"title":"ExpenseReportOut","description":"IFRS 2 expense schedule for a period. `complete` is false when a grant could not be measured; such\ngrants are listed with their status and left out of `total_expense` — never given a guessed value.","examples":[{"company_id":"co-lefkara","complete":true,"excluded_grants":0,"lines":[{"cumulative_end":"190.00","cumulative_start":"100.00","expense":"90.00","fair_value_per_option":"0.90","forfeited_unvested":0,"grant_id":"G-1","holder_id":"eleni","method":"black_scholes","plan_id":"esop-2025","quantity":480,"remaining":"242.00","reversed":"0.00","status":"ok","total_fair_value":"432.00"}],"period_end":"2026-06-30","period_start":"2026-01-01","total_expense":"90.00"}]},"FundEvent.CapitalCallIssued":{"type":"object","title":"CapitalCallIssued","description":"A call header. Its lines are CallAllocated events, one per partner with a non-zero line, weighted by uncalled commitment just before the call.","properties":{"type":{"type":"string","const":"CapitalCallIssued","enum":["CapitalCallIssued"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"call_id":{"type":"string"},"purpose":{"type":"string","enum":["investment","management_fee","fund_expenses"]},"total":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"due_date":{"type":"string","format":"date"}},"required":["type","date","call_id","purpose","total","due_date"],"additionalProperties":false},"FundEvent.ContributionReceived":{"type":"object","title":"ContributionReceived","description":"Money a partner paid against its line of a call; several partial payments are allowed.","properties":{"type":{"type":"string","const":"ContributionReceived","enum":["ContributionReceived"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"call_id":{"type":"string"},"lp_id":{"type":"string"},"amount":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."}},"required":["type","date","event_id","call_id","lp_id","amount"],"additionalProperties":false},"FundEvent.DistributionDeclared":{"type":"object","title":"DistributionDeclared","description":"A distribution header, paid on its date. Its lines are DistributionAllocated events: return of capital weighted by unreturned contributed capital, gain weighted by called capital.","properties":{"type":{"type":"string","const":"DistributionDeclared","enum":["DistributionDeclared"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"distribution_id":{"type":"string"},"return_of_capital":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"gain":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"position_id":{"type":"string"}},"required":["type","date","distribution_id","return_of_capital","gain"],"additionalProperties":false},"FundEvent.ExpensePaid":{"type":"object","title":"ExpensePaid","description":"A fee or a fund expense paid out of the fund's cash. The fee is entered, not computed (fee bases differ from one LPA to the next); call_id names the call that funded it, when one did.","properties":{"type":{"type":"string","const":"ExpensePaid","enum":["ExpensePaid"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"category":{"type":"string","enum":["management_fee","fund_expenses"]},"amount":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"call_id":{"type":"string"}},"required":["type","date","event_id","category","amount"],"additionalProperties":false},"FundEvent.FundConstituted":{"type":"object","title":"FundConstituted","description":"The fund exists from this date. Every other event must be on or after it, and there is one.","properties":{"type":{"type":"string","const":"FundConstituted","enum":["FundConstituted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"name":{"type":"string"},"legal_form":{"type":"string","enum":["partnership","company","spv"]},"currency":{"type":"string"},"vintage_year":{"type":"integer"},"target_size":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"registration_number":{"type":"string"}},"required":["type","date","name","legal_form","currency","vintage_year"],"additionalProperties":false},"FundEvent.InvestmentMade":{"type":"object","title":"InvestmentMade","description":"A tranche into a position. The first tranche opens the position; a later one with the same position_id is a follow-on into the same portfolio company. The cost is the transaction price, which is the fair value at initial recognition (IFRS 13): the position is carried at cost until a mark.","properties":{"type":{"type":"string","const":"InvestmentMade","enum":["InvestmentMade"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"position_id":{"type":"string"},"portfolio_name":{"type":"string"},"instrument":{"type":"string","enum":["shares","asa","loan"]},"cost":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"quantity":{"type":"integer","description":"Number of shares or options; a whole number."},"class_label":{"type":"string"},"round_label":{"type":"string"}},"required":["type","date","event_id","position_id","portfolio_name","instrument","cost"],"additionalProperties":false},"FundEvent.InvestmentMarked":{"type":"object","title":"InvestmentMarked","description":"The fair value of the whole remaining position on this date. A portfolio round price is an input to a mark, never the mark itself; disclosure_ref cites the company's disclosure it rests on.","properties":{"type":{"type":"string","const":"InvestmentMarked","enum":["InvestmentMarked"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"position_id":{"type":"string"},"fair_value":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"basis":{"type":"string","enum":["recent_round","recent_transaction","write_down","write_off","other"]},"source":{"type":"string"},"disclosure_ref":{"type":"string"}},"required":["type","date","event_id","position_id","fair_value","basis","source"],"additionalProperties":false},"FundEvent.InvestmentRealized":{"type":"object","title":"InvestmentRealized","description":"An exit. cost_realized is the part of the remaining cost that leaves the position; when it is all of it, the exit is full and the position closes, with nothing left to value. remaining_fair_value is the value of what stays, and acts as a mark on the exit's date.","properties":{"type":{"type":"string","const":"InvestmentRealized","enum":["InvestmentRealized"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"event_id":{"type":"string","description":"Your id for this event; unique within the company. Posting it again answers 409 unique_event_key."},"position_id":{"type":"string"},"proceeds":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"cost_realized":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."},"remaining_fair_value":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."}},"required":["type","date","event_id","position_id","proceeds","cost_realized","remaining_fair_value"],"additionalProperties":false},"FundEvent.LpAdmitted":{"type":"object","title":"LpAdmitted","description":"A partner joins with a commitment. Only before the first call: a later closing changes every allocation weight retroactively (equalisation), which v1 does not model.","properties":{"type":{"type":"string","const":"LpAdmitted","enum":["LpAdmitted"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"lp_id":{"type":"string"},"legal_name":{"type":"string","description":"Name as it goes into the register (Cap. 113 s.105(1)(a))."},"kind":{"type":"string","enum":["natural_person","legal_entity"],"description":"One of the listed values."},"partner_role":{"type":"string","enum":["lp","gp"]},"commitment":{"type":"string","pattern":"^-?[0-9]+(\\.[0-9]+)?$","description":"Decimal string."}},"required":["type","date","lp_id","legal_name","kind","partner_role","commitment"],"additionalProperties":false},"FundEvent.StatementWithdrawn":{"type":"object","title":"StatementWithdrawn","description":"A statement is withdrawn, never edited; a replacement is a new statement with its own id. While a statement stands, an event dated on or before it that changes its figures is refused. A withdrawn statement stands on no date, not even before the withdrawal's; the store refuses a withdrawal dated after the day it is recorded.","properties":{"type":{"type":"string","const":"StatementWithdrawn","enum":["StatementWithdrawn"]},"date":{"type":"string","format":"date","description":"The event's date, ISO. Projections on a date see the events on or before it."},"statement_id":{"type":"string"},"reason":{"type":"string"}},"required":["type","date","statement_id","reason"],"additionalProperties":false},"FundIn":{"properties":{"name":{"type":"string","title":"Name","description":"The fund's name; must not be blank."}},"type":"object","required":["name"],"title":"FundIn","description":"A new fund; the caller becomes its admin.","examples":[{"name":"Akamas Ventures I"}]},"FundRecordedOut":{"properties":{"events":{"items":{"$ref":"#/components/schemas/EventRecorded"},"type":"array","title":"Events"}},"type":"object","required":["events"],"title":"FundRecordedOut","description":"One recording in a fund: the event posted first, then the lines the road wrote with it.","examples":[{"events":[{"event_key":"call-3","event_type":"CapitalCallIssued","seq":7},{"event_key":"call-3|lp-a","event_type":"CallAllocated","seq":8}]}]},"GuardRefusalOut":{"properties":{"detail":{"$ref":"#/components/schemas/Rejection"}},"type":"object","required":["detail"],"title":"GuardRefusalOut","description":"409 Conflict: the request was understood and refused by a named capital rule. Nothing was recorded.","examples":[{"detail":{"detail":"allotment of 2000 exceeds authorized 1000","guard":"guard_allotment_within_authorized"}}]},"HealthOut":{"properties":{"status":{"type":"string","title":"Status","description":"Always ok when the app answers."},"deployment":{"type":"string","title":"Deployment","description":"saas | on-prem."},"edition":{"type":"string","title":"Edition","description":"saas | on-prem."}},"type":"object","required":["status","deployment","edition"],"title":"HealthOut","description":"Liveness of the installation. Needs no token.","examples":[{"deployment":"saas","edition":"saas","status":"ok"}]},"HolderLineOut":{"properties":{"holder_id":{"type":"string","title":"Holder Id","description":"The holder's id in this company's ledger."},"outstanding":{"type":"integer","title":"Outstanding","description":"Shares held on the date, all classes."},"options":{"type":"integer","title":"Options","description":"Unexercised options outstanding on the date."},"pct_outstanding":{"type":"string","title":"Pct Outstanding","description":"Share of issued shares, percent with 4 decimals (display only)."},"pct_fully_diluted":{"type":"string","title":"Pct Fully Diluted","description":"Share of the fully diluted count, percent with 4 decimals."},"legal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Legal Name","description":"Name as entered in the register."},"kind":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Kind","description":"natural_person | legal_entity | joint_holding."},"address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Address","description":"Address as entered in the register."},"date_entered":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Entered","description":"Date entered in the register, ISO."},"date_ceased":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Date Ceased","description":"Date ceased to be a member, ISO."},"consideration_recorded":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consideration Recorded","description":"Decimal string, cents."}},"type":"object","required":["holder_id","outstanding","options","pct_outstanding","pct_fully_diluted"],"title":"HolderLineOut","description":"One register line. The s.105 particulars are null when the holder has no HolderRecorded on the\ndate; `consideration_recorded` is the subscription consideration recorded on the shares held, null for\na holder that never held shares. The capacity (nominee, trustee) is not here: it is outside the\nregister extract (Cap. 113 s.112).","examples":[{"address":"12 Makariou Ave, 1065 Nicosia, Cyprus","consideration_recorded":"3500.00","date_entered":"2025-02-01","holder_id":"andreas","kind":"natural_person","legal_name":"Andreas Christofi","options":0,"outstanding":3500,"pct_fully_diluted":"70.0000","pct_outstanding":"77.7778"}]},"InstrumentOut":{"properties":{"instrument_id":{"type":"string","title":"Instrument Id","description":"The AsaSubscribed event_id."},"holder_id":{"type":"string","title":"Holder Id","description":"The investor."},"amount":{"type":"string","title":"Amount","description":"Invested amount, decimal string."},"discount":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Discount","description":"Conversion discount as a fraction (0.20 = 20 %)."},"valuation_cap":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valuation Cap","description":"Valuation cap, decimal string."},"longstop_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Longstop Date","description":"Longstop date, ISO."},"converted_by":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Converted By","description":"event_id of the InstrumentConverted, once converted."}},"type":"object","required":["instrument_id","holder_id","amount"],"title":"InstrumentOut","description":"ASA / convertible instrument: not shares until conversion, hence separate from lines and outside FD.","examples":[{"amount":"50000","discount":"0.20","holder_id":"angel-1","instrument_id":"asa-1","longstop_date":"2027-06-30","valuation_cap":"4000000"}]},"PoolLineOut":{"properties":{"plan_id":{"type":"string","title":"Plan Id","description":"The option plan."},"pool_size":{"type":"integer","title":"Pool Size","description":"Options the plan may grant."},"granted":{"type":"integer","title":"Granted","description":"Options granted from the pool."},"exercised":{"type":"integer","title":"Exercised","description":"Options exercised."},"available":{"type":"integer","title":"Available","description":"What the pool can still grant."}},"type":"object","required":["plan_id","pool_size","granted","exercised","available"],"title":"PoolLineOut","description":"An option plan's pool on `as_of`.","examples":[{"available":520,"exercised":0,"granted":480,"plan_id":"esop-2025","pool_size":1000}]},"RatioAdjustmentOut":{"properties":{"class_id":{"type":"string","title":"Class Id","description":"The protected class."},"method":{"type":"string","title":"Method","description":"The anti-dilution method of the class."},"original_price":{"type":"string","title":"Original Price","description":"The class's original issue price."},"ratio_before":{"type":"string","title":"Ratio Before","description":"Conversion ratio before the round."},"conversion_price_before":{"type":"string","title":"Conversion Price Before","description":"CP1."},"a":{"type":"string","title":"A","description":"A: shares outstanding before the round (as the method counts them)."},"b":{"type":"string","title":"B","description":"B: shares the new money would buy at CP1."},"c":{"type":"integer","title":"C","description":"C: shares actually issued in the round."},"conversion_price_after":{"type":"string","title":"Conversion Price After","description":"CP2."},"ratio_after":{"type":"string","title":"Ratio After","description":"Conversion ratio after the round."}},"type":"object","required":["class_id","method","original_price","ratio_before","conversion_price_before","a","b","c","conversion_price_after","ratio_after"],"title":"RatioAdjustmentOut","description":"Anti-dilution adjustment in NVCA notation: CP2 = CP1 × (A + B) / (A + C); exact fractions are given\nas \"num/den\" strings.","examples":[{"a":"5000","b":"625","c":1250,"class_id":"pref-a","conversion_price_after":"360","conversion_price_before":"400","method":"broad_based_weighted_average","original_price":"400","ratio_after":"1.111111","ratio_before":"1"}]},"RegisterOut":{"properties":{"company_id":{"type":"string","title":"Company Id","description":"The company of the path."},"as_of":{"type":"string","title":"As Of","description":"The projection date, ISO."},"total_outstanding":{"type":"integer","title":"Total Outstanding","description":"Issued shares on the date."},"total_options":{"type":"integer","title":"Total Options","description":"Outstanding options on the date."},"fully_diluted":{"type":"integer","title":"Fully Diluted","description":"Outstanding shares plus outstanding options."},"lines":{"items":{"$ref":"#/components/schemas/HolderLineOut"},"type":"array","title":"Lines","description":"One line per holder."},"instruments_total":{"type":"string","title":"Instruments Total","description":"Sum of unconverted instrument amounts, decimal string."},"instruments":{"items":{"$ref":"#/components/schemas/InstrumentOut"},"type":"array","title":"Instruments","description":"ASAs and convertibles, outside the share count."}},"type":"object","required":["company_id","as_of","total_outstanding","total_options","fully_diluted","lines","instruments_total","instruments"],"title":"RegisterOut","description":"The register of members projected from the ledger on `as_of`.","examples":[{"as_of":"2026-10-12","company_id":"co-lefkara","fully_diluted":5000,"instruments":[],"instruments_total":"0","lines":[{"address":"12 Makariou Ave, 1065 Nicosia, Cyprus","consideration_recorded":"3500.00","date_entered":"2025-02-01","holder_id":"andreas","kind":"natural_person","legal_name":"Andreas Christofi","options":0,"outstanding":3500,"pct_fully_diluted":"70.0000","pct_outstanding":"77.7778"}],"total_options":500,"total_outstanding":4500}]},"RegisterSummaryOut":{"properties":{"total_outstanding":{"type":"integer","title":"Total Outstanding","description":"Issued shares."},"total_options":{"type":"integer","title":"Total Options","description":"Outstanding options."},"fully_diluted":{"type":"integer","title":"Fully Diluted","description":"Shares plus options."},"capitalization":{"type":"string","title":"Capitalization","description":"As-converted capitalization, exact."},"instruments_total":{"type":"string","title":"Instruments Total","description":"Unconverted instruments, decimal string."}},"type":"object","required":["total_outstanding","total_options","fully_diluted","capitalization","instruments_total"],"title":"RegisterSummaryOut","description":"Totals of a register, before or after a modelled round.","examples":[{"capitalization":"5000","fully_diluted":5000,"instruments_total":"50000","total_options":500,"total_outstanding":4500}]},"Rejection":{"properties":{"guard":{"type":"string","title":"Guard","description":"Stable machine name of the rule that refused (a `guard_*` function, or a named ledger rule such as `unique_event_key`). Safe to branch on."},"detail":{"type":"string","title":"Detail","description":"The rule's explanation, in English."}},"type":"object","required":["guard","detail"],"title":"Rejection","description":"A capital rule that refused the request: the guard's stable name and its sentence.","examples":[{"detail":"allotment of 2000 exceeds authorized 1000","guard":"guard_allotment_within_authorized"}]},"RoundModelOut":{"properties":{"company_id":{"type":"string","title":"Company Id","description":"The company of the path."},"as_of":{"type":"string","title":"As Of","description":"The register date the round is modelled on, ISO."},"round_id":{"type":"string","title":"Round Id","description":"The round's id from the terms."},"price":{"type":"string","title":"Price","description":"Price per share, cents."},"price_exact":{"type":"string","title":"Price Exact","description":"Price per share, exact fraction."},"pricing_capitalization":{"type":"string","title":"Pricing Capitalization","description":"The capitalization the price is computed on."},"capitalization_post":{"type":"string","title":"Capitalization Post","description":"Capitalization after the round."},"pool_top_up":{"type":"integer","title":"Pool Top Up","description":"Options added to the pool before the round (pool shuffle)."},"pool_pct_post":{"type":"string","title":"Pool Pct Post","description":"Pool share after the round, percent."},"post_money_implied":{"type":"string","title":"Post Money Implied","description":"Price × post capitalization."},"new_money":{"type":"string","title":"New Money","description":"Sum of subscriptions."},"shares_issued":{"type":"integer","title":"Shares Issued","description":"New shares, subscriptions and conversions."},"subscriptions":{"items":{"$ref":"#/components/schemas/SubscriptionOut"},"type":"array","title":"Subscriptions","description":"New money."},"conversions":{"items":{"$ref":"#/components/schemas/ConversionOut"},"type":"array","title":"Conversions","description":"Instruments converting."},"adjustments":{"items":{"$ref":"#/components/schemas/RatioAdjustmentOut"},"type":"array","title":"Adjustments","description":"Anti-dilution adjustments."},"dilution":{"items":{"$ref":"#/components/schemas/DilutionLineOut"},"type":"array","title":"Dilution","description":"Before/after table."},"proposed_events":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Proposed Events","description":"Events in the same shape POST /companies/{company_id}/events accepts."},"pre":{"$ref":"#/components/schemas/RegisterSummaryOut","description":"Totals before."},"post":{"$ref":"#/components/schemas/RegisterSummaryOut","description":"Totals after."}},"type":"object","required":["company_id","as_of","round_id","price","price_exact","pricing_capitalization","capitalization_post","pool_top_up","pool_pct_post","post_money_implied","new_money","shares_issued","subscriptions","conversions","adjustments","dilution","proposed_events","pre","post"],"title":"RoundModelOut","description":"What the round would do — nothing is recorded. proposed_events are the ledger events a writer would\npost one by one to make it real; post is the register they would produce.","examples":[{"adjustments":[],"as_of":"2026-10-12","capitalization_post":"6250","company_id":"co-lefkara","conversions":[],"dilution":[{"after":"3500","before":"3500","key":"andreas","kind":"holder","pct_after":"56.0000","pct_before":"70.0000"}],"new_money":"500000","pool_pct_post":"8.0000","pool_top_up":0,"post":{"capitalization":"6250","fully_diluted":6250,"instruments_total":"50000","total_options":500,"total_outstanding":5750},"post_money_implied":"2500000","pre":{"capitalization":"5000","fully_diluted":5000,"instruments_total":"50000","total_options":500,"total_outstanding":4500},"price":"400.00","price_exact":"400","pricing_capitalization":"5000","proposed_events":[{"class_id":"common","date":"2026-10-12","event_id":"seed-fund-x","holder_id":"fund-x","price_per_share":"400.00","quantity":1250,"round_id":"seed","type":"Allotment"}],"round_id":"seed","shares_issued":1250,"subscriptions":[{"amount":"500000","holder_id":"fund-x","paid":"500000.00","remainder":"0.00","shares":1250}]}]},"StatementIn":{"description":"Issue a partner statement on a date with the figures the fund ledger gives.","examples":[{"date":"2026-06-30","statement_id":"st-2026-q2"}],"properties":{"statement_id":{"description":"Your id for the statement; unique within the fund.","title":"Statement Id","type":"string"},"date":{"description":"Statement date, ISO (YYYY-MM-DD).","title":"Date","type":"string"}},"required":["statement_id","date"],"title":"StatementIn","type":"object"},"SubscriptionOut":{"properties":{"holder_id":{"type":"string","title":"Holder Id","description":"The subscriber."},"amount":{"type":"string","title":"Amount","description":"Amount subscribed, decimal string."},"shares":{"type":"integer","title":"Shares","description":"Whole shares the amount buys."},"paid":{"type":"string","title":"Paid","description":"shares × price, cents."},"remainder":{"type":"string","title":"Remainder","description":"amount − paid: the part that buys no whole share."}},"type":"object","required":["holder_id","amount","shares","paid","remainder"],"title":"SubscriptionOut","description":"One new-money subscription in a modelled round.","examples":[{"amount":"500000","holder_id":"fund-x","paid":"500000.00","remainder":"0.00","shares":1250}]},"ValidationErrorOut":{"properties":{"detail":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Detail","description":"FastAPI's list of {loc, msg, type} entries."}},"type":"object","required":["detail"],"title":"ValidationErrorOut","description":"422 for a query or path parameter FastAPI could not read (for example `as_of=yesterday`). An event\nbody Ekvi cannot read answers 422 with an `ErrorOut` instead.","examples":[{"detail":[{"loc":["query","as_of"],"msg":"Input should be a valid date","type":"date_parsing"}]}]},"VestingLineOut":{"properties":{"grant_id":{"type":"string","title":"Grant Id","description":"The OptionGranted event_id."},"holder_id":{"type":"string","title":"Holder Id","description":"The grantee."},"plan_id":{"type":"string","title":"Plan Id","description":"The option plan."},"quantity":{"type":"integer","title":"Quantity","description":"Options granted."},"vested":{"type":"integer","title":"Vested","description":"Options vested on the date."},"exercised":{"type":"integer","title":"Exercised","description":"Options exercised on or before the date."},"cancelled":{"type":"integer","title":"Cancelled","description":"Options cancelled on or before the date."},"lapsed":{"type":"integer","title":"Lapsed","description":"Options that expired unexercised (projection from expiry_date)."},"exercisable":{"type":"integer","title":"Exercisable","description":"Vested, not exercised, not cancelled, not lapsed."},"outstanding":{"type":"integer","title":"Outstanding","description":"Granted minus exercised, cancelled and lapsed."},"fmv_at_grant":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fmv At Grant","description":"FMV per share on the grant date, if recorded."},"valuation_at_grant":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Valuation At Grant","description":"valuation_id in force on the grant date."}},"type":"object","required":["grant_id","holder_id","plan_id","quantity","vested","exercised","cancelled","lapsed","exercisable","outstanding"],"title":"VestingLineOut","description":"One option grant and where its vesting stands on `as_of`.","examples":[{"cancelled":0,"exercisable":120,"exercised":0,"fmv_at_grant":"1.50","grant_id":"G-1","holder_id":"eleni","lapsed":0,"outstanding":480,"plan_id":"esop-2025","quantity":480,"valuation_at_grant":"val-2025","vested":120}]}},"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"An API token from Profile → API tokens in the portal."}}},"tags":[{"name":"Companies","description":"The companies you are a member of."},{"name":"Ledger","description":"The append-only event ledger of a company: read it, append to it."},{"name":"Projections","description":"What the ledger says on a date: register, vesting, pools."},{"name":"Modelling","description":"Read-only calculations: a round, an IFRS 2 schedule."},{"name":"Funds","description":"Funds you are a member of and their own ledger."},{"name":"Service","description":"Liveness."}]}