IwiConnect API docs

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

  1. Ask for a URL. POST /upload/presign with the file name, MIME type and size. You get back a document id, a URL and a set of form fields.
  2. 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.
  3. Confirm. POST /upload/complete with 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

CategoryAccepted typesUse for
document.pdf, .doc, .docx, .jpg, .jpeg, .pngProject attachments and responses.
image.png, .jpg, .jpeg, .webpLogos and branding.
gisLayer.geojson, .json, .kml, .zip, .topojsonRohe 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

post /upload/presign files:write

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.

FieldTypeNotes
fileNamestringrequiredOriginal name, including extension. Shown to recipients.
mimeTypestringrequiredMust match the category.
sizeintegerrequiredBytes. Must be positive and at most 104857600.
categorystringoptionaldocument, image or gisLayer. Defaults to document.
Request
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"
  }'
Response
{
  "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.

Request · S3
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.

Node
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

post /upload/complete files:write

Verifies the object landed, records its size and type, and makes the document attachable. Returns 404 if the bytes never arrived.

Request
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.

Fragment
{
  "files": [
    {
      "id": "b3f2a1c4-55de-4f7a-9c21-0a5d6e8f4b12",
      "name": "cultural-impact-assessment.pdf"
    }
  ]
}

Downloading

get /download/{id} files:read

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.