{"openapi":"3.1.0","info":{"title":"Cogrant Search API","description":"Partner-facing API in front of Cogrant's grant-search workflows.\n\n**Auth.** Every request must carry a partner API key as ``Authorization: Bearer <key>``.\n\n**Async jobs.** POST ``/v1/searches`` returns 202 with a ``job_id``. Poll ``GET /v1/searches/{job_id}`` until ``status == \"done\"``, then fetch results from ``GET /v1/searches/{job_id}/matches``. Alternatively, supply ``callback_url`` on creation and the gateway will POST the completed job to it.\n\n**Idempotency.** Include an ``Idempotency-Key`` header on POST requests to make them safely retryable; a replay returns the original job and sets ``Idempotency-Replayed: true`` on the response.\n\n**Errors.** Every error response uses a single envelope::\n\n```\n{\"error\": {\"code\": \"JOB_NOT_FOUND\", \"message\": \"...\", \"request_id\": \"req_...\", \"details\": {...}}}\n```\n\nEvery response also carries an ``X-Request-Id`` header — quote it in support requests and it'll match our logs.","contact":{"name":"Cogrant","url":"https://www.cogrant.eu/","email":"hello@cogrant.eu"},"version":"0.1.0"},"paths":{"/health":{"get":{"tags":["health"],"summary":"Liveness probe","description":"Cheap liveness check. Does not hit external dependencies.\n\nUsed by Render's health check and UptimeRobot.","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/searches":{"post":{"tags":["searches"],"summary":"Create a new grant-search job","description":"Kicks off an async grant search for the company specified in the request payload. Returns 202 with a ``job_id`` immediately; the search typically takes 1-4 minutes.\n\n**Pipeline.** The company is classified once (if new), then every enriched grant passes hard eligibility filters (deadline, geography, organisation type, size, age, support forms, consortium stance); survivors receive a four-axis relevance score (capabilities, verticality, archetype, expertise) in [0, 1.05] and only pairs at or above the threshold (default 0.90) reach the LLM sanity check (up to 150 per run). Passing pairs become Search Matches.\n\n**Idempotency.** Pass an ``Idempotency-Key`` header to make the call safely retryable. A repeat with the same key returns the original job and sets ``Idempotency-Replayed: true``.\n\n**Example.**\n\n```bash\ncurl -sS -X POST https://api.cogrant.eu/v1/searches \\\n  -H 'Authorization: Bearer cog_live_...' \\\n  -H 'Content-Type: application/json' \\\n  -H 'Idempotency-Key: 2a8e4c-sprint42' \\\n  -d '{\"payload\": {\"company_id\": \"recABCDEFGHIJKLMN\"}}'\n```","operationId":"create_search_v1_searches_post","security":[{"PartnerApiKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Idempotency-Key"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobCreate"}}}},"responses":{"202":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobAccepted"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Request body failed validation.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}}}}},"/v1/searches/{job_id}":{"get":{"tags":["searches"],"summary":"Fetch the current state of a search job","description":"Polls the job. ``status`` transitions ``queued`` → ``running`` → ``done`` or ``failed``. The full result set lives under ``GET /v1/searches/{job_id}/matches`` — this endpoint stays lightweight for frequent polling.\n\n**Result payload** (on ``done``): funnel counts (``reviewed`` / ``eligible`` / ``evaluated`` / ``matches_created`` / ``dismissed``), ``model`` (the LLM used), ``tokens`` (incl. ``thoughts``), ``score_threshold``, ``scores`` (per-pair relevance scores with axis breakdowns) and ``sanity`` (one compact LLM verdict per evaluated pair, pass and dismissed alike).\n\nA reasonable polling cadence is every 5–10 seconds; searches typically complete within 60–120 seconds.","operationId":"get_search_v1_searches__job_id__get","security":[{"PartnerApiKey":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JobView"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}},"/v1/searches/{job_id}/matches":{"get":{"tags":["searches"],"summary":"Fetch the full list of matches for a completed search job","description":"Returns every match the search produced, each with the parsed match analysis and the full grant-details JSON. Only callable once the job reaches ``status=done`` — earlier polls return 409 with a hint to keep polling the status endpoint.\n\nThe match analysis includes the relevance score breakdown (``Relevance Score``: total, four axis sub-scores, tier, best-fit role) and the v2 sanity-check fields: ``Participation Mode`` (Sole applicant / Coordinator / Partner — the role every verdict was scored against), ``Can Participate``, ``Worth Pursuing``, and a structured ``Partner Role`` block (role, specific contribution, work-package sketch, plausible budget share, confidence, upstream role assessment).\n\nPayloads are substantial (hundreds of KB for a rich search); call this once per job rather than on a polling loop.","operationId":"get_search_matches_v1_searches__job_id__matches_get","security":[{"PartnerApiKey":[]}],"parameters":[{"name":"job_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Job Id"}},{"name":"authorization","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Authorization"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MatchesView"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"404":{"description":"Resource not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"409":{"description":"Conflict with current resource state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorEnvelope"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}}}}}},"components":{"schemas":{"Administrative":{"properties":{"application_language":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Application Language","description":"Accepted languages (e.g. ``[\"English\"]``)."},"submission_process_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Submission Process Description","description":"Broad description of the submission process (pitch to jury, physical mailing, etc.)."},"submission_portal_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Submission Portal Name","description":"Name of the portal/IT system."},"submission_portal_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Submission Portal Url","description":"URL of the submission portal."},"required_submission_documents":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Submission Documents","description":"Documents the applicant must attach at submission — business plan, letters of intent, ethics self-assessments, signed declarations, audited financials, CVs, etc. Format/page limits in parentheses where stated."},"post_award_administration_process":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Post Award Administration Process","description":"Project administration after winning — reporting frequency, milestones, payment triggers."},"official_contact_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Official Contact Email","description":"Primary email for applicant support / Q&A."},"audit_and_reporting_burden":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Audit And Reporting Burden","description":"Admin heaviness — auditor certificates, timesheets, etc."}},"additionalProperties":true,"type":"object","title":"Administrative"},"ApplicationStage":{"properties":{"stage_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Stage Name","description":"Name of the stage or batch (e.g. ``Concept Note``, ``Full Proposal``, ``Batch 1``). Only forward-looking stages are included — past batches are omitted."},"deadline_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deadline Date","description":"Deadline for this stage in ``YYYY-MM-DD``. Empty when no hard deadline is approaching for a continuous call."},"deadline_conditions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Deadline Conditions","description":"Conditions attached to this deadline (e.g. ``Only for applicants who passed stage 1``)."}},"additionalProperties":true,"type":"object","title":"ApplicationStage"},"ClarificationQuestion":{"properties":{"question":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Question","description":"Short plain-language question, answerable yes/no."},"type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type","description":"Always ``boolean`` today."}},"additionalProperties":true,"type":"object","title":"ClarificationQuestion","description":"One yes/no question surfaced to the company.\n\nAppears under ``Clarification Questions``, ``Objective Questions``,\nand ``Activities Questions``. Answering resolves an ``Unclear`` item\nto ``Pass`` / ``Fail`` / ``Dealbreaker`` (for eligibility) or\nupgrades a fit level (for objective / activity)."},"Consortium":{"properties":{"required":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Required","description":"``Required`` / ``Optional`` / ``Single Applicant`` — whether a consortium is mandatory, optional, or disallowed."},"potential_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Potential Role","description":"``Coordinator`` or ``Partner``. Present only when a consortium is allowed."},"missing_partner_roles":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Missing Partner Roles","description":"Roles required to make the project credible/eligible that the company likely needs to recruit (pilot site, certified lab, public authority, manufacturing line, university, etc.). Informational only — does NOT influence any verdict."}},"additionalProperties":true,"type":"object","title":"Consortium","description":"Consortium expectations for this match."},"CoreMetadata":{"properties":{"managing_authority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Managing Authority","description":"Name of the institution managing or administering the grant."},"funding_provider":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Funding Provider","description":"Ultimate source of the funds (e.g. European Union, NextGenerationEU, a national ministry)."},"program_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Program Name","description":"Official title of the overarching programme the grant belongs to."},"grant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grant Name","description":"Official title of this specific funding call, in English."},"grant_name_native":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Grant Name Native","description":"Official grant name in the native language of the funding call."},"short_grant_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Grant Name","description":"Simplified, short name for the grant in plain language — heavy technical jargon stripped. English."},"reference_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Id","description":"Official call ID or reference number; ``null`` if none."}},"additionalProperties":true,"type":"object","title":"CoreMetadata"},"EligibilityAndConsortia":{"properties":{"geography_level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geography Level","description":"``European`` / ``Regional`` / ``National`` / ``Local``."},"eligible_countries_organisation":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Countries Organisation","description":"Countries where the applicant organisation must be registered (only populated for Regional/National)."},"eligible_countries_activities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Countries Activities","description":"Countries where project activities must be carried out."},"eligible_local_regions_organisation":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Local Regions Organisation","description":"Specific regions/municipalities of registration for Local calls."},"eligible_local_regions_activities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Local Regions Activities","description":"Specific regions/municipalities for project activities, Local calls."},"geographical_conditions_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Geographical Conditions Description","description":"Prose covering nuances: where the project must be executed vs. where the applicant is registered vs. where beneficiaries are."},"eligible_legal_forms_picklist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Legal Forms Picklist","description":"All that apply — e.g. ``Private Business``, ``Non-profit``, ``Research Institution``, ``Public Institution``, ``Natural Person``."},"min_trl":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Trl","description":"Minimum Technology Readiness Level required to be already achieved at the time of application (1–9)."},"max_trl":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Trl","description":"Maximum Technology Readiness Level already achieved at the time of application (1–9)."},"eligibility_conditions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligibility Conditions","description":"Constraints on organisations applying (age, sector, certifications, infrastructure, etc.)."},"consortium_setup":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consortium Setup","description":"``Mono-beneficiary Only`` / ``Consortium Required`` / ``Consortium Optional``."},"min_consortium_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Consortium Size","description":"Minimum number of partners required (``1`` if mono-beneficiary allowed)."},"min_countries_in_consortium":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Min Countries In Consortium","description":"Minimum number of different eligible countries in the consortium."},"required_consortium_roles":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Required Consortium Roles","description":"Specific roles or entity types required in the consortium."},"exclusion_criteria":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Exclusion Criteria","description":"Explicit conditions / entity types that CANNOT apply (e.g. ``Undertakings in difficulty``, ``Tobacco sector``)."},"explicit_org_priority_criteria":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Explicit Org Priority Criteria","description":"Characteristics the call EXPLICITLY rewards with bonus points or priority status. Weights appear in parentheses."},"implicit_org_priority_criteria":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Implicit Org Priority Criteria","description":"Profiles the call clearly favours through its language or design even without formal bonus points. Each entry cites the specific signal from the call that supports the inference."}},"additionalProperties":true,"type":"object","title":"EligibilityAndConsortia"},"EligibilityCriterion":{"properties":{"criteria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Criteria","description":"The criterion in up to 10 words."},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status","description":"``Pass`` / ``Fail`` / ``Unclear`` / ``Dealbreaker``."}},"additionalProperties":true,"type":"object","title":"EligibilityCriterion","description":"One row in ``Eligibility Criteria`` / ``Priority Criteria``."},"ErrorBody":{"properties":{"code":{"$ref":"#/components/schemas/ErrorCode","description":"Machine-readable error code."},"message":{"type":"string","title":"Message","description":"Human-readable summary."},"request_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Request Id","description":"Gateway request ID — quote this in support requests."},"details":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Details","description":"Optional structured context (field errors, job status, etc.)."}},"type":"object","required":["code","message"],"title":"ErrorBody"},"ErrorCode":{"type":"string","enum":["INVALID_REQUEST","UNAUTHORIZED","FORBIDDEN","JOB_NOT_FOUND","JOB_NOT_READY","JOB_FAILED","RATE_LIMITED","INTERNAL_ERROR"],"title":"ErrorCode","description":"Machine-readable error codes.\n\nKeep this list short and stable. Adding a code is a minor version bump in\npartner-docs terms; renaming one is a breaking change."},"ErrorEnvelope":{"properties":{"error":{"$ref":"#/components/schemas/ErrorBody"}},"type":"object","required":["error"],"title":"ErrorEnvelope","description":"Top-level error response body."},"Financials":{"properties":{"currency":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Currency","description":"Currency the grant is awarded in (``EUR``, ``USD``, …)."},"overall_total_call_budget":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Overall Total Call Budget","description":"Total budget for the entire funding call across all projects."},"number_of_projects_awarded":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Number Of Projects Awarded","description":"How many applicants will be awarded."},"pre_financing_percentage":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pre Financing Percentage","description":"Percentage of the grant given upfront as an advance payment."},"funding_tiers":{"anyOf":[{"items":{"$ref":"#/components/schemas/FundingTier"},"type":"array"},{"type":"null"}],"title":"Funding Tiers","description":"Per-condition funding brackets."},"support_forms_picklist":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Support Forms Picklist","description":"All applicable forms of support — e.g. ``Grant - Lump Sum``, ``Grant - Actual Costs``, ``Grant - De Minimis``, ``Blended Finance``, ``Equity Investment``, ``Loan``, ``Voucher``, ``Prize``, ``Scholarship/Fellowship``, ``Tax Credit``, ``Subsidy``, ``In-kind Support``."},"support_form_conditions":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Support Form Conditions","description":"Conditions for support forms including co-financing and own-contribution rules, stacking rules with other grants, minimum cash thresholds."},"eligible_costs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Eligible Costs","description":"Line items that can be funded. Nuances / caps / choices in parentheses (e.g. ``Overheads capped at 15%``)."},"non_eligible_costs":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Non Eligible Costs","description":"Explicitly named costs that are NOT funded."},"funds_disbursement_timeline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Funds Disbursement Timeline","description":"When and how funds are given to the company (e.g. reimbursed quarterly based on milestones) and what conditions trigger disbursement."}},"additionalProperties":true,"type":"object","title":"Financials"},"FundingTier":{"properties":{"tier_condition":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tier Condition","description":"Condition for this funding bracket (e.g. ``SMEs``, ``Standard``)."},"minimum_funding_ticket":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minimum Funding Ticket","description":"Minimum grant amount for this tier."},"maximum_funding_ticket":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maximum Funding Ticket","description":"Maximum grant amount for this tier."},"max_funding_intensity_pct":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Funding Intensity Pct","description":"Max percentage of eligible costs covered for this tier."}},"additionalProperties":true,"type":"object","title":"FundingTier"},"GrantDetails":{"properties":{"core_metadata":{"anyOf":[{"$ref":"#/components/schemas/CoreMetadata"},{"type":"null"}]},"timelines":{"anyOf":[{"$ref":"#/components/schemas/Timelines"},{"type":"null"}]},"financials":{"anyOf":[{"$ref":"#/components/schemas/Financials"},{"type":"null"}]},"eligibility_and_consortia":{"anyOf":[{"$ref":"#/components/schemas/EligibilityAndConsortia"},{"type":"null"}]},"scope_and_activities":{"anyOf":[{"$ref":"#/components/schemas/ScopeAndActivities"},{"type":"null"}]},"scope_batches":{"anyOf":[{"items":{"$ref":"#/components/schemas/ScopeBatch"},"type":"array"},{"type":"null"}],"title":"Scope Batches","description":"Separate thematic tracks if the call defines them, otherwise an empty array."},"administrative":{"anyOf":[{"$ref":"#/components/schemas/Administrative"},{"type":"null"}]}},"additionalProperties":true,"type":"object","title":"GrantDetails","description":"Structured grant metadata attached to every Search Match.\n\nEvery section is produced by a dedicated upstream agent; fields\nmarked ``Optional`` reflect that absence of data is common and we\nnever want partners to parse defensively around nulls they already\nhandle elsewhere."},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HealthResponse":{"properties":{"status":{"type":"string","title":"Status"},"env":{"type":"string","title":"Env"},"version":{"type":"string","title":"Version"}},"type":"object","required":["status","env","version"],"title":"HealthResponse"},"JobAccepted":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"$ref":"#/components/schemas/JobStatus"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["job_id","status","created_at"],"title":"JobAccepted","description":"202 response body."},"JobCreate":{"properties":{"payload":{"type":"object","title":"Payload","description":"Search input. Two shapes are accepted:\n\n* **Existing company** — ``{\"company_id\": \"rec...\"}`` where the record ID points at an existing row in Cogrant's Companies table.\n* **New company** — ``{\"company_name\": \"...\", \"company_description\": \"...\", \"country\": \"...\", \"website\": \"...\"}``. The gateway creates the Companies row on the fly (Organisation Type set to ``Private Business``) and then runs the search against the new record. ``website`` is optional; ``country`` must match one of the values on Companies → Country.\n\nMixing ``company_id`` with new-company fields is rejected with 422."},"callback_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Callback Url","description":"Optional HTTPS URL. If set, the gateway POSTs the completed job body (same shape as ``GET /v1/searches/{job_id}``) once the run finishes. Callbacks are fire-and-forget — partners should still treat polling as the source of truth."}},"type":"object","required":["payload"],"title":"JobCreate","description":"What partners POST when creating a job. Shape is workflow-specific but\nwe keep a loose `payload` dict here; each endpoint validates its own shape.","examples":[{"callback_url":"https://partner.example/webhooks/cogrant","payload":{"company_id":"recABCDEFGHIJKLMN"}},{"payload":{"company_description":"Fermentation-based protein for the food industry.","company_name":"Acme Bio","country":"Lithuania","website":"https://acme.bio"}}]},"JobStatus":{"type":"string","enum":["queued","running","done","failed"],"title":"JobStatus"},"JobView":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"status":{"$ref":"#/components/schemas/JobStatus"},"workflow_kind":{"$ref":"#/components/schemas/WorkflowKind"},"company_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Company Id","description":"Airtable record ID of the company this search ran against. For new-company requests this is the row the gateway created on the fly, so partners can capture it here; for existing-company requests it echoes the ``company_id`` that was submitted."},"result":{"anyOf":[{"type":"object"},{"type":"null"}],"title":"Result"},"error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Error"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["job_id","status","workflow_kind"],"title":"JobView","description":"Public-facing job representation. Hides internal Airtable record IDs."},"MatchDetails":{"properties":{"Short Grant Title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Short Grant Title","description":"Reader-friendly title with heavy codes stripped, keeping the core distinguishing keywords."},"Hook sentence":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Hook Sentence","description":"Short commercial tagline teasing what the grant achieves (verb + change-the-world style)."},"Match Summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match Summary","description":"2–3 sentences explaining why the company should or should not apply. Decision-informing analysis only — does not retell the company's own story."},"Match Level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match Level","description":"Overall fit verdict summarising eligibility + objective + activity signals."},"Eligibility Status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Eligibility Status","description":"Hard requirement match verdict — ``Eligible``, ``Likely Eligible``, ``Unclear``, ``Not Eligible``, or ``No Information``."},"Eligibility Criteria":{"anyOf":[{"items":{"$ref":"#/components/schemas/EligibilityCriterion"},"type":"array"},{"type":"null"}],"title":"Eligibility Criteria","description":"Every explicitly stated eligibility rule, each with a status."},"Priority Criteria":{"anyOf":[{"items":{"$ref":"#/components/schemas/EligibilityCriterion"},"type":"array"},{"type":"null"}],"title":"Priority Criteria","description":"Explicitly stated priority (bonus-point) eligibility criteria, each with a status."},"Clarification Questions":{"anyOf":[{"items":{"$ref":"#/components/schemas/ClarificationQuestion"},"type":"array"},{"type":"null"}],"title":"Clarification Questions","description":"Yes/no questions used to resolve gaps on Hard Eligibility. Answering them reassigns ``Unclear`` items to ``Pass``, ``Fail``, or ``Dealbreaker``."},"formatted_criteria":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Formatted Criteria","description":"Pre-rendered bullet list of all eligibility criteria + status."},"all_questions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"All Questions","description":"All open clarification / upgrade questions flattened to a single string for convenience."},"Objectives Fit Level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Objectives Fit Level","description":"``Strong fit`` / ``Potential fit`` / ``No fit``."},"Objectives summa summarum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Objectives Summa Summarum","description":"One sentence summarising thematic alignment between the company's objective and the call's intent."},"Objective Questions":{"anyOf":[{"items":{"$ref":"#/components/schemas/ClarificationQuestion"},"type":"array"},{"type":"null"}],"title":"Objective Questions","description":"A single high-stakes question designed to reframe ``Potential fit`` into ``Strong fit`` at the objective level. Empty for ``Strong fit`` or ``No fit``."},"Activity Fit Level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activity Fit Level","description":"``Strong fit`` / ``Potential fit`` / ``No fit``."},"Activities summa summarum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Activities Summa Summarum","description":"One sentence summarising how well the work the company performs matches the work the call finances."},"Activities Questions":{"anyOf":[{"items":{"$ref":"#/components/schemas/ClarificationQuestion"},"type":"array"},{"type":"null"}],"title":"Activities Questions","description":"A single high-stakes question designed to reframe ``Potential fit`` into ``Strong fit`` at the activity level."},"Budget Fit Level":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Fit Level","description":"``Strong fit`` / ``Potential fit`` / ``No fit`` — whether the funding range matches the company's funding goals."},"Budget summa summarum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Budget Summa Summarum","description":"Plain-words comparison of the call's funding range and the company's funding goals."},"Consortium":{"anyOf":[{"$ref":"#/components/schemas/Consortium"},{"type":"null"}],"description":"Consortium expectations, potential role, and missing roles."}},"additionalProperties":true,"type":"object","title":"MatchDetails","description":"Analyst-style decision block attached to every Search Match.\n\nProduced by the Grant–Company Match Sanity Checker agent. The shape\nis stable enough to expose in the public schema, but individual\nfield values are free-form strings.\n\nEvery field has both a Python-safe attribute name and the Title Case\nalias that appears on the wire. Partners should read the Title Case\nkeys from JSON; the Python names only matter inside the gateway."},"MatchView":{"properties":{"match_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Match Id"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"match":{"anyOf":[{"$ref":"#/components/schemas/MatchDetails"},{"type":"object"}],"title":"Match","description":"Analyst-style decision block attached to this match — see ``MatchDetails`` schema for field-by-field documentation."},"grant":{"anyOf":[{"$ref":"#/components/schemas/GrantDetails"},{"type":"object"}],"title":"Grant","description":"Structured grant metadata — see ``GrantDetails`` schema for field-by-field documentation."}},"type":"object","title":"MatchView","description":"A single Search Match row as exposed to partners.\n\n``match`` is the decision block produced by the Grant–Company Match\nSanity Checker agent (parsed from the ``Raw Json`` field on the\nSearch Matches row).\n\n``grant`` is the structured grant metadata (parsed from the\n``Grant Details JSON`` lookup on the linked Grants row).\n\nBoth are typed but use ``extra=\"allow\"`` everywhere, so evolving\nupstream shapes never break a response and unknown fields are\npreserved verbatim. See :mod:`app.models.match_details` and\n:mod:`app.models.grant_details` for per-field descriptions."},"MatchesView":{"properties":{"job_id":{"type":"string","format":"uuid","title":"Job Id"},"count":{"type":"integer","title":"Count"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"matches":{"items":{"$ref":"#/components/schemas/MatchView"},"type":"array","title":"Matches"}},"type":"object","required":["job_id","count","matches"],"title":"MatchesView","description":"Response body for ``GET /v1/searches/{job_id}/matches``."},"ProjectDuration":{"properties":{"duration_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Duration Type","description":"One of ``Years`` / ``Months`` / ``Days``."},"minimum_duration":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minimum Duration","description":"Minimum allowed full project duration; ``null`` if none."},"maximum_duration":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Maximum Duration","description":"Maximum allowed full project duration; ``null`` if none."}},"additionalProperties":true,"type":"object","title":"ProjectDuration"},"ScopeAndActivities":{"properties":{"funding_call_goal":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Funding Call Goal","description":"One-sentence statement of the call's overarching impact."},"problem_solved_summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Problem Solved Summary","description":"2–4 sentence plain-language summary of the concrete problem this call exists to solve. ``Not explicitly stated in source`` when the call does not describe it."},"related_policies_and_acts":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Related Policies And Acts","description":"Specific policies, laws, acts, or strategic documents this call implements (e.g. EU Green Deal, AI Act)."},"project_nature_typology":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Project Nature Typology","description":"Core natures — ``R&D``, ``Infrastructure/CapEx``, ``Training/Upskilling``, ``Commercialization/Go-to-Market``, ``Event/Networking``, ``Policy/Advocacy``, ``Sustainability Transition``."},"technology_focus_typology":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Technology Focus Typology","description":"Technological / thematic focuses — ``Digital/ICT``, ``DeepTech/AI``, ``GreenTech/CleanTech``, ``Health/MedTech``, ``BioTech``, ``AgTech``, ``Social Innovation``, ``Creative/Cultural``, ``Sector-Agnostic``."},"primary_beneficiary_typology":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Primary Beneficiary Typology","description":"Who ultimately benefits — ``Startups``, ``Scaleups/SMEs``, ``Academia/Researchers``, ``Public Sector``, ``General Citizens``, ``Marginalized Groups``."},"supported_activities":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Supported Activities","description":"Eligible activity types. One bullet = one activity."},"expected_concrete_deliverables":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Expected Concrete Deliverables","description":"Tangible outputs, near-term outcomes, and systemic impacts the project is expected to produce."},"project_evaluation_priority_criteria":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Project Evaluation Priority Criteria","description":"Criteria used to score the application (e.g. ``[IMPACT]`` prefix, weights/max points in parentheses)."}},"additionalProperties":true,"type":"object","title":"ScopeAndActivities"},"ScopeBatch":{"properties":{"batch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Batch Name","description":"Name of the thematic track / challenge / lot / topic / sub-call. Only present when the call explicitly defines separate tracks."},"batch_description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Batch Description","description":"One-sentence description of what this batch funds."},"batch_specific_eligibility":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Batch Specific Eligibility","description":"ONLY eligibility conditions that diverge from the main eligibility_and_consortia fields."},"batch_specific_deliverables":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Batch Specific Deliverables","description":"ONLY deliverables that diverge from ``expected_concrete_deliverables``."}},"additionalProperties":true,"type":"object","title":"ScopeBatch"},"Timelines":{"properties":{"application_opening_date":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Opening Date","description":"When the call officially opens for submissions (``YYYY-MM-DD``)."},"is_continuous_call":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Continuous Call","description":"``true`` if the call is open continuously until funds run out; ``false`` if it has a hard deadline."},"application_process_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Application Process Type","description":"``Single-stage`` / ``Two-stage`` / ``Continuous with cut-offs`` / ``Rolling evaluation``."},"early_closure_possible":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Early Closure Possible","description":"``true`` if the call can close before the deadline (e.g. after a cap on applications or funds exhausted)."},"early_closure_conditions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Early Closure Conditions","description":"Exact conditions for early closure."},"application_stages":{"anyOf":[{"items":{"$ref":"#/components/schemas/ApplicationStage"},"type":"array"},{"type":"null"}],"title":"Application Stages","description":"Forward-looking stages/batches with their deadlines."},"evaluation_process":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Evaluation Process","description":"Steps of the evaluation process — what is assessed at each step plus the expected timeline from submission to result."},"project_duration":{"anyOf":[{"$ref":"#/components/schemas/ProjectDuration"},{"type":"null"}],"description":"Allowed project length bounds."},"project_start_date_rules":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Start Date Rules","description":"When the project must start (e.g. immediately after contract signature, a specific date, within 3 months of award)."},"project_timeline_conditions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Project Timeline Conditions","description":"Other conditions related to the implementation timeline."}},"additionalProperties":true,"type":"object","title":"Timelines"},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"WorkflowKind":{"type":"string","enum":["search","match_check_a","match_check_b"],"title":"WorkflowKind"}},"securitySchemes":{"PartnerApiKey":{"type":"http","description":"Your partner API key, passed as ``Authorization: Bearer <key>``. Contact Cogrant to issue or rotate.","scheme":"bearer"}}},"tags":[{"name":"searches","description":"Create and poll grant-search jobs. Jobs run asynchronously — POST to create, then either poll GET or wait for your ``callback_url`` to fire."},{"name":"health","description":"Liveness and readiness probes."}]}