Using the API
File uploads
Documents go straight to storage using a short lived presigned URL. The API hands out the URL and records the result, but the bytes never pass through it.
The flow
- Ask for a URL.
POST /upload/presignwith the file name, MIME type and size. You get back a document id, a URL and a set of form fields. - POST the file. Send the fields plus the file itself as multipart form data to the URL, in that order. This request goes to S3, not to IwiConnect, and carries no API key.
- Confirm.
POST /upload/completewith the document id. The document is now real and can be attached to a project or an engagement.
Skipping step three leaves an orphaned record that is cleaned up later and cannot be attached to anything.
Limits
| Category | Accepted types | Use for |
|---|---|---|
document | .pdf, .doc, .docx, .jpg, .jpeg, .png | Project attachments and responses. |
image | .png, .jpg, .jpeg, .webp | Logos and branding. |
gisLayer | .geojson, .json, .kml, .zip, .topojson | Rohe boundaries, iwi accounts only. |
Maximum file size is 100 MB. The category also decides which MIME types are accepted, so sending a spreadsheet as a document fails validation at step one rather than halfway through the upload.
Request a URL
Returns a presigned POST target that expires in a few minutes. Ask for it immediately before you upload, not at the start of a long job.
| Field | Type | Notes | |
|---|---|---|---|
fileName | string | required | Original name, including extension. Shown to recipients. |
mimeType | string | required | Must match the category. |
size | integer | required | Bytes. Must be positive and at most 104857600. |
category | string | optional | document, image or gisLayer. Defaults to document. |
curl -X POST "$IWICONNECT_URL/upload/presign" \
-H "Authorization: Bearer $IWICONNECT_KEY" \
-H 'Content-Type: application/json' \
-d '{
"fileName": "cultural-impact-assessment.pdf",
"mimeType": "application/pdf",
"size": 2451233,
"category": "document"
}'
{
"success": true,
"message": "Upload URL created",
"status_code": 200,
"response_object": {
"documentId": "b3f2a1c4-55de-4f7a-9c21-0a5d6e8f4b12",
"url": "https://iwiconnect-documents.s3.ap-southeast-6.amazonaws.com/",
"fields": {
"key": "documents/b3f2a1c4-55de-4f7a-9c21-0a5d6e8f4b12/cultural-impact-assessment.pdf",
"policy": "eyJleHBpcmF0aW9uIjoi...",
"x-amz-signature": "3a1f..."
}
}
}
Upload the bytes
Every entry in fields becomes a form field, in the order given, followed by the file last. S3 rejects the upload if the file comes first.
curl -X POST 'https://iwiconnect-documents.s3.ap-southeast-6.amazonaws.com/' \ -F 'key=documents/b3f2a1c4-.../cultural-impact-assessment.pdf' \ -F 'policy=eyJleHBpcmF0aW9uIjoi...' \ -F 'x-amz-signature=3a1f...' \ -F 'file=@cultural-impact-assessment.pdf'
A successful upload returns 204 with an empty body. There is no envelope here, because this is S3 answering, not IwiConnect.
const form = new FormData();
for (const [name, value] of Object.entries(fields)) {
form.append(name, value);
}
form.append("file", fileBlob, fileName);
const upload = await fetch(url, { method: "POST", body: form });
if (!upload.ok) throw new Error(`Upload failed: ${upload.status}`);
Confirm the upload
Verifies the object landed, records its size and type, and makes the document attachable. Returns 404 if the bytes never arrived.
curl -X POST "$IWICONNECT_URL/upload/complete" \
-H "Authorization: Bearer $IWICONNECT_KEY" \
-H 'Content-Type: application/json' \
-d '{ "documentId": "b3f2a1c4-55de-4f7a-9c21-0a5d6e8f4b12" }'
Attaching the document
Pass the document id in the files array when you create a project or respond to one.
{
"files": [
{
"id": "b3f2a1c4-55de-4f7a-9c21-0a5d6e8f4b12",
"name": "cultural-impact-assessment.pdf"
}
]
}
Downloading
Returns a short lived signed URL for a document you can already see through a project or an engagement. The link expires quickly, so fetch it at the moment you need it rather than storing it.
Documents live in Auckland. Production storage runs in the AWS Auckland region, so document data stays on New Zealand soil.