Help topics
API reference
Bulk import
Upload a rent roll as CSV. Each row creates the property, unit, tenant, lease and deposit in one call.
Download the template
GET
/import/templatescope tenure:readReturns text/csv with the column headings and two example rows.
Property,Unit,Unit Code,Unit Type,Tenant Name,Phone,WhatsApp,M-Pesa Number,Rent,Deposit,Start Date,Billing Day,Balance
Riverside Court,B12,B12,two_bedroom,Faith Wafula,0722145880,,0733902471,25000,25000,01/03/2025,1,0
Riverside Court,B14,B14,one_bedroom,John Mwangi,0733902471,,,18000,18000,15/06/2025,15,18000Import tenancies
POST
/import/tenanciesscope tenure:writeQuery parameters
| Field | Type | Required | Description |
|---|---|---|---|
dry_run | true | false | no | Default true: validate every row, write nothing. Send false to commit. |
property_id | uuid | no | Property for rows with a blank Property cell. Use it for single-building files. |
Body
JSON { "csv": "<file contents>" }, or the raw file with Content-Type: text/plain. Maximum 1 MB.
CSV columns
One row per occupied unit. Headings are case- and punctuation-insensitive, and common aliases are accepted (House No for Unit, Mobile for Phone).
| Column | Required | Format / default |
|---|---|---|
| Unit | yes | Door label, e.g. B12 |
| Tenant Name | yes | Full name |
| Phone | yes | Kenyan mobile, any common format |
| Rent | yes | Monthly, in shillings: 25000, 25,000 or KES 25,000 |
| Property | yes* | Found by name or created. *Or pass property_id |
| Unit Code | no | Paybill account reference. Default: the Unit label |
| Unit Type | no | Default one_bedroom |
| no | Default: Phone | |
| M-Pesa Number | no | The number the tenant pays from, if different |
| Deposit | no | Deposit held, in shillings. Default 0 |
| Start Date | no | YYYY-MM-DD or DD/MM/YYYY. Default today |
| Billing Day | no | 1–31. Default 5 |
| Balance | no | Owed today, in shillings. Becomes one opening invoice |
| ID Number | no | National ID |
Example request
curl -X POST "https://api.astralyngroup.com/tenure/v1/import/tenancies?dry_run=true" \
-H "Authorization: Bearer $TOKEN" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"csv":"Property,Unit,Tenant Name,Phone,Rent\nRiverside Court,B12,Faith Wafula,0722145880,25000\nRiverside Court,B14,John Mwangi,,18000"}'Response
200 for a dry run or when nothing was written; 201 when at least one row was imported. Row problems never fail the request: read rows.
200 OK
{
"dryRun": true,
"totalRows": 2,
"imported": 1,
"alreadyImported": 0,
"failed": 1,
"rows": [
{ "line": 2, "outcome": "imported", "unitLabel": "B12", "tenantName": "Faith Wafula" },
{ "line": 3, "outcome": "failed", "unitLabel": "B14", "tenantName": "John Mwangi",
"problem": "No phone number. Every tenant needs one — it is how they are matched and told." }
]
}| Field | Type | Required | Description |
|---|---|---|---|
dryRun | boolean | yes | Echoes the dry_run you sent. |
totalRows | integer | yes | Data rows in the file, excluding the header. |
imported | integer | yes | Rows created (or that would be, on a dry run). |
alreadyImported | integer | yes | Rows skipped because the unit is already let. |
failed | integer | yes | Rows with a problem. Nothing was written for them. |
rows[].line | integer | yes | Spreadsheet line number; the header is line 1. |
rows[].outcome | string | yes | imported | already_imported | failed |
rows[].problem | string | no | Why the row failed, in plain words. |
rows[].leaseId | uuid | no | The new lease. Only when committed. |
fileProblem | string | no | The whole file is unusable (no rows, missing required column). rows is empty. |
Behaviour
- Validate first. Call with
dry_run=true, fix the failed rows, then call again withdry_run=false. - Safe to re-send. Units are matched by Unit Code and tenants by phone. A unit that already has a live lease is reported as
already_imported, never duplicated. - Partial success. Each row commits on its own; one bad row does not block the rest.
- Unit Codes must be unique within the file. M-Pesa payments are matched on them.
- No messages are sent. Imported tenants hear from Nyumbisha at their next rent date.
- No payment history. A Balance becomes one opening invoice; past receipts are not recreated.