---
title: "Ask a supplier contact for data through an emailed link (supplier portal; default workspace only)"
method: POST
path: "/supplier-portal/requests"
tags: ["Supplier portal"]
---

# Ask a supplier contact for data through an emailed link (supplier portal; default workspace only)

`POST /supplier-portal/requests`

## Request body

- SupplierPortalRequestInput
  - `contactEmail` string, required
  - `contactName` string, required
  - `delivery` 'greentally' | 'self' — How the link reaches the contact. "greentally" (the default when omitted): Core emails the contact, From "<sender name> via GreenTally" with Reply-To the acting user's verified email. "self": the customer sends it from their own mailbox (the client opens a mailto: draft) and Core sends nothing.
  - `dueDate` string, date, nullable, required
  - `message` string, required
  - `periodEnd` string, date, required — Exclusive: the day after the last day.
  - `periodStart` string, date, required
  - `sections` SupplierPortalSections, required
    - `activityData` boolean, required
    - `allocation` boolean, required
    - `evidenceFiles` boolean, required
    - `productFootprint` boolean, required
    - `sbtiStatus` boolean, required
  - `siteIds` string[], required
  - `supplierId` string, required

## Response `201`

The request, sent (emailStatus says whether the email went out)

- SupplierPortalRequestResponse
  - `data` SupplierPortalRequestDetail, required
    - `acceptedAt` string, date-time, nullable, required
    - `cancelledAt` string, date-time, nullable, required
    - `contactEmail` string, required
    - `contactName` string, required
    - `dueDate` string, date, nullable, required
    - `emailStatus` 'pending' | 'sent' | 'logged' | 'failed' | 'self', required — Outcome of GreenTally's email: pending, sent, logged (no relay configured) or failed; "self" when the customer sent the link from their own mailbox (no email from Core). After a self reminder it still describes the last GreenTally email.
    - `expiresAt` string, date-time, required
    - `id` string, required
    - `lastRemindedAt` string, date-time, nullable, required
    - `nextReminderAt` string, date-time, nullable, required — Earliest time a GreenTally reminder may go out: one calendar month after the last email GreenTally sent (the initial send or a reminder; self-delivered sends do not count). When GreenTally sent none it is the request's sentAt, so a reminder is allowed now. Null when the stored status takes no reminder (submitted, accepted, cancelled). May lie in the past, meaning a reminder is allowed now. A self reminder is never capped.
    - `openedAt` string, date-time, nullable, required
    - `pendingSubmissionId` string, required — Empty unless the latest submission awaits review.
    - `periodEnd` string, date, required
    - `periodStart` string, date, required
    - `reminderCount` integer, required
    - `sections` SupplierPortalSections, required
      - `activityData` boolean, required
      - `allocation` boolean, required
      - `evidenceFiles` boolean, required
      - `productFootprint` boolean, required
      - `sbtiStatus` boolean, required
    - `sentAt` string, date-time, required
    - `status` 'sent' | 'opened' | 'submitted' | 'returned' | 'accepted' | 'cancelled' | 'expired', required
    - `submittedAt` string, date-time, nullable, required
    - `supplierId` string, required
    - `supplierName` string, required
    - `files` SupplierPortalFile[], required
      - `contentType` string, required
      - `fileName` string, required
      - `id` string, required
      - `sizeBytes` integer, required
      - `uploadedAt` string, date-time, required
    - `leftoverNetZeroRows` SupplierPortalLeftoverRows
      - `instruments` integer, required
      - `sbti` boolean, required
    - `message` string, required
    - `sites` SupplierPortalSite[], required
      - `id` string, required
      - `name` string, required
      - `supplyPoints` string[], required
    - `submissions` SupplierPortalSubmission[], required
      - `answers` SupplierPortalAnswers, required — The questionnaire answers (supplierportal.Answers); validated in Go.
      - `id` string, required
      - `reviewComment` string, required
      - `reviewStatus` 'pending' | 'accepted' | 'returned', required
      - `reviewedAt` string, date-time, nullable, required
      - `reviewedBy` string, required
      - `submittedAt` string, date-time, required
      - `version` integer, required

## Other responses

- `400` — Bad Request
- `401` — Unauthorized
- `403` — Forbidden
- `404` — Not Found
- `409` — Conflict
- `429` — EMAIL_DAILY_LIMIT: the organization has used its daily allowance of emails GreenTally sends (SUPPLIER_PORTAL_DAILY_EMAIL_LIMIT, default 50, counted per UTC day across request sends, GreenTally reminders and return notices). Only delivery "greentally" is refused, before anything is written; delivery "self" is never counted or blocked. details.limit is the daily limit and details.resetsAt the RFC 3339 UTC time the count resets (the next UTC midnight). The message suggests sending the link from the customer's own email.

## Changes

- **2026-10-05** `04eabb8ebb47` — 1 info
  - endpoint added

[Change history](https://skmtc.dev/greentally/apis/esgai-api/changes/supplier-portal/requests/post.md)

---

[API](https://skmtc.dev/greentally/apis/esgai-api.md) · [All operations](https://skmtc.dev/greentally/apis/esgai-api/llms.txt) · [OpenAPI document](https://skmtc.dev/greentally/apis/esgai-api/revisions/461a0ebc7731?raw)
