Skip to content

Matches API

The Matches API provides AI-powered company-grant matching with a hybrid scoring algorithm. It supports both real-time match calculation and persisted match management with user interaction tracking.

All match endpoints require authentication and are scoped to the current user's tenant.

Scoring Algorithm

Matches are scored using a weighted hybrid algorithm:

Component Weight Description
Semantic similarity 25% Embedding cosine similarity (all-mpnet-base-v2)
Rule-based criteria 30% Country, NACE codes, company size
Carbon alignment 25% Carbon categories, certifications, taxonomy objectives
Collaborative 10% Peer interaction signals from similar companies
Recency 10% Deadline urgency scoring

Disqualifying rules:

  • Country mismatch returns a score of 0
  • Company size mismatch (when grant explicitly restricts sizes) returns a score of 0
  • Carbon-focused grants receive a 1.2x bonus (capped at 1.0)

Endpoints

GET /matches

List persisted matches with optional filtering. This is the primary frontend-aligned endpoint for match listing.

Authentication: Required

{
  "items": [
    {
      "id": "d4e5f6a7-b8c9-0123-def0-456789012345",
      "company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
      "grant_id": "b1c2d3e4-f5a6-7890-bcde-f12345678901",
      "score": 0.87,
      "rule_score": 0.92,
      "semantic_score": 0.81,
      "recency_score": 0.95,
      "collaborative_score": 0.65,
      "carbon_score": 0.88,
      "match_reasons": [
        "Country match: DE",
        "NACE code overlap: M71",
        "Carbon category match: renewable_energy",
        "ISO_14001 certification recognized"
      ],
      "is_viewed": true,
      "is_saved": false,
      "is_dismissed": false,
      "created_at": "2025-01-15T10:30:00Z",
      "grant": {
        "id": "b1c2d3e4-f5a6-7890-bcde-f12345678901",
        "title": "Green Innovation Fund",
        "deadline": "2025-06-30T23:59:59Z",
        "is_carbon_focused": true
      }
    }
  ],
  "total": 42,
  "page": 1,
  "page_size": 20
}
curl -X GET "https://api.carbonconnect.io/api/v1/matches?company_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890&min_score=0.5&status=saved&page=1" \
  -H "Authorization: Bearer <token>"

Query Parameters:

Parameter Type Default Description
company_id UUID -- Filter by company ID
status string -- Filter: saved, dismissed, active
min_score float -- Minimum weighted score (0.0-1.0)
page integer 1 Page number
page_size integer 20 Items per page (1-100)

POST /matches/calculate

Trigger match calculation for a company. Calculates matches and persists them to the database.

Authentication: Required

{
  "company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
{
  "task_id": "e5f6a7b8-c9d0-1234-ef01-567890123456"
}
curl -X POST https://api.carbonconnect.io/api/v1/matches/calculate \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"}'

Request Body:

Field Type Required Description
company_id UUID Yes Company to calculate matches for

Synchronous Execution

Currently, match calculation runs synchronously and returns a pseudo task_id. Future versions will support asynchronous Celery-based calculation.

Status Codes:

Code Description
200 Calculation complete
401 Not authenticated
404 Company not found or wrong tenant

GET /matches/stats

Get match statistics for a company or entire tenant.

Authentication: Required

{
  "total": 42,
  "by_eligibility": {
    "saved": 8,
    "dismissed": 3,
    "active": 31
  },
  "score_distribution": {
    "min": 0.23,
    "max": 0.95,
    "avg": 0.67
  }
}
curl -X GET "https://api.carbonconnect.io/api/v1/matches/stats?company_id=a1b2c3d4-e5f6-7890-abcd-ef1234567890" \
  -H "Authorization: Bearer <token>"

Query Parameters:

Parameter Type Default Description
company_id UUID -- Filter by company ID

GET /matches/match/{match_id}

Get a single match by its ID with full details including the associated grant.

Authentication: Required

curl -X GET https://api.carbonconnect.io/api/v1/matches/match/d4e5f6a7-b8c9-0123-def0-456789012345 \
  -H "Authorization: Bearer <token>"

Path Parameters:

Parameter Type Description
match_id UUID Match ID

Status Codes:

Code Description
200 Match returned
401 Not authenticated
404 Match not found or wrong tenant

PATCH /matches/match/{match_id}/action

Update the status of a match (save, dismiss, or restore).

Authentication: Required

{
  "action": "save"
}
{
  "id": "d4e5f6a7-b8c9-0123-def0-456789012345",
  "is_saved": true,
  "is_dismissed": false,
  "score": 0.87
}
curl -X PATCH https://api.carbonconnect.io/api/v1/matches/match/d4e5f6a7-b8c9-0123-def0-456789012345/action \
  -H "Authorization: Bearer <token>" \
  -H "Content-Type: application/json" \
  -d '{"action": "save"}'

Request Body:

Field Type Required Description
action string Yes Action: save, dismiss, or restore

Action Behavior:

Action Effect
save Sets is_saved=true, is_dismissed=false
dismiss Sets is_dismissed=true, is_saved=false
restore Sets both is_saved=false, is_dismissed=false

Status Codes:

Code Description
200 Action applied, updated match returned
400 Invalid action value
401 Not authenticated
404 Match not found or wrong tenant

GET /matches/{company_id}

Calculate and return real-time matches for a company using the hybrid matching algorithm. Results are not persisted by default.

Authentication: Required

{
  "items": [
    {
      "grant": {
        "id": "b1c2d3e4-f5a6-7890-bcde-f12345678901",
        "title": "Green Innovation Fund",
        "is_carbon_focused": true
      },
      "score": 0.87,
      "rule_score": 0.92,
      "semantic_score": 0.81,
      "recency_score": 0.95,
      "collaborative_score": 0.65,
      "carbon_score": 0.88,
      "match_reasons": [
        "Country match: DE",
        "NACE code overlap: M71"
      ]
    }
  ],
  "total": 15,
  "company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
curl -X GET "https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890?min_score=0.3&page=1&page_size=10" \
  -H "Authorization: Bearer <token>"

Path Parameters:

Parameter Type Description
company_id UUID Company ID

Query Parameters:

Parameter Type Default Description
page integer 1 Page number
page_size integer 20 Items per page (1-100)
min_score float 0.0 Minimum score threshold (0-1)

GET /matches/{company_id}/saved

Get persisted matches for a company, including user interaction state.

Authentication: Required

curl -X GET "https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890/saved?page=1" \
  -H "Authorization: Bearer <token>"

Path Parameters:

Parameter Type Description
company_id UUID Company ID

Query Parameters:

Parameter Type Default Description
page integer 1 Page number
page_size integer 20 Items per page (1-100)

POST /matches/{company_id}/refresh

Recalculate matches for a company and optionally persist the results.

Authentication: Required

{
  "items": [...],
  "total": 20,
  "company_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
}
curl -X POST "https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890/refresh?save_results=true&limit=30" \
  -H "Authorization: Bearer <token>"

Path Parameters:

Parameter Type Description
company_id UUID Company ID

Query Parameters:

Parameter Type Default Description
save_results boolean true Persist results to database
limit integer 20 Maximum matches to calculate (1-100)

PATCH /matches/{company_id}/{grant_id}/view

Mark a match as viewed.

Authentication: Required

curl -X PATCH https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890/b1c2d3e4-f5a6-7890-bcde-f12345678901/view \
  -H "Authorization: Bearer <token>"

Status Codes:

Code Description
204 Match marked as viewed
404 Match or company not found

PATCH /matches/{company_id}/{grant_id}/save

Toggle a match's saved state.

Authentication: Required

curl -X PATCH "https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890/b1c2d3e4-f5a6-7890-bcde-f12345678901/save?saved=true" \
  -H "Authorization: Bearer <token>"

Query Parameters:

Parameter Type Default Description
saved boolean true Saved state value

PATCH /matches/{company_id}/{grant_id}/dismiss

Toggle a match's dismissed state.

Authentication: Required

curl -X PATCH "https://api.carbonconnect.io/api/v1/matches/a1b2c3d4-e5f6-7890-abcd-ef1234567890/b1c2d3e4-f5a6-7890-bcde-f12345678901/dismiss?dismissed=true" \
  -H "Authorization: Bearer <token>"

Query Parameters:

Parameter Type Default Description
dismissed boolean true Dismissed state value

Match Response Schema

MatchResponse (persisted)

Field Type Description
id UUID Match record ID
company_id UUID Company ID
grant_id UUID Grant ID
score float Weighted total score (0-1)
rule_score float Rule-based component (0-1)
semantic_score float Semantic similarity component (0-1)
recency_score float Recency/urgency component (0-1)
collaborative_score float Collaborative filtering (0-1)
carbon_score float Carbon alignment component (0-1)
match_reasons string[] Human-readable match explanations
score_breakdown object Full score breakdown details
is_viewed boolean Whether user has viewed this match
is_saved boolean Whether user has saved this match
is_dismissed boolean Whether user has dismissed this match
grant object Full grant details (when included)
created_at string ISO 8601 creation timestamp
updated_at string ISO 8601 last update timestamp

MatchResultResponse (real-time)

Field Type Description
grant object Full grant details
score float Weighted total score (0-1)
rule_score float Rule-based component (0-1)
semantic_score float Semantic similarity (0-1)
recency_score float Recency/urgency (0-1)
collaborative_score float Collaborative filtering (0-1)
carbon_score float Carbon alignment (0-1)
match_reasons string[] Human-readable match explanations