Metadata-Version: 2.4
Name: comhom-sdk
Version: 0.1.1
Summary: The official SDK for integrating homelessness data into the Comhom Platform.
Author: Socialit
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: jsonschema~=4.25.1
Dynamic: author
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: license-file
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# comhom-sdk

Official Python SDK for integrating homelessness service data into the [Comhom Platform](https://platform.comhom.eu).

Upload, validate, and manage beneficiary answer data from JSON or CSV files — via a Python API or the command line.

## Features

- **Upload** answers in JSON or CSV format, validated against the live platform schema
- **Validate** files locally before sending data
- **Generate** synthetic test data that conforms to your organization's schema
- **Delete** all answers for a beneficiary in sandbox or production
- **Python API** for scripting and pipeline integration

## Installation

```bash
pip install comhom-sdk
```

Requires **Python 3.10+**. Dependencies are installed automatically.

## Quick start

### Python API

```python
from comhom_sdk import (
    fetch_answer_schema,
    load_api_key_from_file,
    load_answers,
    upload_answers,
    validate_answer_items,
)

api_key = load_api_key_from_file("comhom.key")
answers = load_answers("answers.json")
schema = fetch_answer_schema(api_key=api_key)
validate_answer_items(answers, schema)

result = upload_answers(
    api_key=api_key,
    answers=answers,
    sandbox=True,
)
print(result)  # {"created": ..., "updated": ..., "skipped": ...}
```

### Command line

```bash
python -m comhom_sdk upload \
  --input-file answers.json \
  --api-key-file comhom.key
```

By default, uploads target **sandbox**. Add `--production` for production.

## Prerequisites

1. **API key** — generate one on the Comhom platform. It is downloaded as `comhom.key`, which the SDK uses by default.
2. **Answer file** — JSON or CSV with the required fields (see below).

Store your API key in a plain text file containing only the key:

```text
your-api-key-here
```

Keep `comhom.key` out of source control.

## Answer data format

Each row is one answer. Required fields:

| Field | Description |
|---|---|
| `respondent_code` | Stable, pseudonymous identifier for the respondent |
| `question_code` | Code of the question being answered |
| `value` | The answer (format depends on question type; see below) |
| `answered_at` | Date the answer was collected (`YYYY-MM-DD`) |
| `consent_signed` | Whether the respondent consented to data use (`true` / `false`) |

Only rows with `consent_signed: true` are loaded.

### Question codes and values

Valid `question_code` values come from the Comhom question catalogue. Examples:

| `question_code` | Type | Example `value` |
|---|---|---|
| `sex_gender` | Single choice | `cisgender_woman` |
| `age` | Single choice | `25_34` |
| `nationality` | Single choice | `national_country` |
| `A2` | Date | `2026-01-10` |
| `A4` | Single choice | `programme_completion` |
| `A5` | Program | `housing_first` (your org's program code) |
| `A6` | Multiple choice | `["cm", "hn"]` |

**Value formats:**

- **Single choice** — one option code (e.g. `sex_gender` → `cisgender_woman`)
- **Multiple choice** — a list of option codes (e.g. `A6` → `["cm", "hn"]`)
- **Date** — `YYYY-MM-DD` (e.g. `A2` → `2026-01-10`)
- **Program (A5)** — a program `code` from your organization (created on the platform first)

### JSON

Use either a top-level array of answers, or an object with an `answers` array:

```json
[
  {
    "respondent_code": "hash_7f3a9c2e",
    "question_code": "sex_gender",
    "answered_at": "2026-06-15",
    "consent_signed": true,
    "value": "cisgender_woman"
  },
  {
    "respondent_code": "hash_7f3a9c2e",
    "question_code": "A6",
    "answered_at": "2026-06-15",
    "consent_signed": true,
    "value": ["cm", "hn"]
  }
]
```

### CSV

Required columns: `respondent_code`, `question_code`, `answered_at`, `consent_signed`, `value`.

```csv
respondent_code,question_code,answered_at,consent_signed,value
hash_7f3a9c2e,sex_gender,2026-06-15,true,cisgender_woman
hash_7f3a9c2e,A6,2026-06-15,true,"[""cm"",""hn""]"
```

`answered_at` is the collection date for each answer. If your source system does not track per-answer timestamps, use one date for the whole export.

### Upload behavior

- Duplicate rows for the same beneficiary/question/date in one file: **last row wins**
- Same value as the latest known snapshot on or before that date: **skipped** (safe to re-upload)
- Same date with a changed value: **updated**
- New date with a changed value: **new history row created**

## Command reference

### `upload`

```bash
python -m comhom_sdk upload -i answers.json -k comhom.key
```

| Option | Short | Required | Description |
|---|---|---|---|
| `--input-file` | `-i` | Yes | Path to `.json` or `.csv` file |
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
| `--production` | `-p` | No | Upload to production (default: sandbox) |
| `--batch-size` | `-b` | No | Answers per request (default `500`) |

### `validate`

Validate a file locally without uploading:

```bash
python -m comhom_sdk validate -i answers.json --errors-file errors.csv
```

| Option | Short | Required | Description |
|---|---|---|---|
| `--input-file` | `-i` | Yes | Path to `.json` or `.csv` file |
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
| `--errors-file` | `-e` | No | Write validation errors to CSV on failure |

### `generate`

Generate synthetic answers using your organization's live schema:

```bash
python -m comhom_sdk generate \
  -n 1000 -c 20 -o synthetic_answers.json -k comhom.key
```

| Option | Short | Required | Description |
|---|---|---|---|
| `--total-answers` | `-n` | Yes | Number of synthetic answers to generate |
| `--output-file` | `-o` | Yes | Output path (`.json` or `.csv`) |
| `--respondent-count` | `-c` | No | Number of respondent codes (default `1`) |
| `--respondent-prefix` | `-p` | No | Prefix for respondent codes (default `R`) |
| `--answered-at` | `-a` | No | Fixed date (`YYYY-MM-DD`) for all answers |
| `--days-back` | `-d` | No | Random date within last N days (default `365`) |
| `--seed` | `-s` | No | Seed for deterministic generation |
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |

### `delete`

Delete all answers for a beneficiary:

```bash
python -m comhom_sdk delete -r hash_7f3a9c2e -k comhom.key
```

| Option | Short | Required | Description |
|---|---|---|---|
| `--respondent-code` | `-r` | Yes | Beneficiary code to delete |
| `--api-key-file` | `-k` | No | Path to API key file (default: `comhom.key`) |
| `--production` | `-p` | No | Delete production data (default: sandbox) |

## Python API reference

| Function | Description |
|---|---|
| `load_api_key_from_file(path)` | Read API key from a text file |
| `load_answers(path)` | Load answers from JSON or CSV |
| `save_answers(answers, path)` | Write answers to JSON or CSV |
| `fetch_answer_schema(api_key=...)` | Download the org-specific upload schema |
| `validate_answer_items(answers, schema)` | Validate answers against the schema |
| `collect_validation_errors(answers, schema)` | Return detailed validation errors |
| `upload_answers(api_key, answers, sandbox=True)` | Upload validated answers in batches |
| `generate_synthetic_answers(schema, ...)` | Generate schema-conformant test data |
| `delete_beneficiary_answers(api_key, respondent_code, sandbox=True)` | Delete a beneficiary's answers |

All network or validation failures raise `UploadSDKError`.

## Troubleshooting

**Upload succeeds** with counts for `created`, `updated`, and `skipped` rows.

**Upload fails** with an error message; no further batches are sent.

**Validation fails** — use `--errors-file` to export every error row for review.

Common issues:

- Wrong API key or insufficient permissions
- Missing required CSV columns
- Invalid date format (must be `YYYY-MM-DD`)
- `consent_signed` not set to `true`
- Invalid `question_code` or option code
- A5 `value` not matching a program code in your organization
- Extra fields that do not match the schema

## License

MIT License. Copyright (c) 2025 Socialit.
