POST /feedback_portal/{portalId}/plain_feedback
Changed onCreate a feedback item without custom fields, attributed to the person who submitted it.
Identical to POST /feedback_portal/{portalId}/feedback except that it accepts no customFields. Everything below applies to both.
Discovering what to send. Do not hard-code a field list. GET /feedback_portal/{portalId}/forms returns each form with its categories and which fields it requires, and GET /feedback_portal/{portalId}/custom_fields returns the field definitions and their allowed values. Both are readable with any key that can read the portal, and a form definition is the same for every visitor — so a client can render a form dynamically and never drift from what the portal actually defines.
Attribution. Send owner (the submitter's email) and, if you have one, submitterId — your own id for that person, which is the stronger key — plus submitterName, without which the portal can only show the local part of the address. A submitter the portal has not seen is created as a portal user who holds no password and can never sign in; they exist so the feedback is attributed to a real person and so their next submission resolves to the same one. A submission that MATCHES an existing submitter also refreshes their stored name and notification address from what you sent, so a rename or an address change on your side needs no separate reconciliation. Omit all of them, or send anonymous: true, and the item is attributed to the portal's anonymous submitter instead. Attributed submissions require pass-through identity to be enabled on the portal.
Retries may duplicate the ITEM, never the person. There is no idempotency key. If a request times out and you re-send it, the submitter resolves to the same person — that is guaranteed — but you may get a second feedback item, which is visible in the portal and deletable. Guard on your own side if a duplicate item matters to you.
Which failures to retry. 503 means the request was fine and Craft could not complete it: retry it. Any 4xx means the request itself is wrong — retrying will not help, so raise it instead. Craft never guesses that two submissions are the same one, so identical content is never deduplicated.
A second credential, for submitting from a browser. This route also accepts Authorization: Bearer <token> in place of x-api-key — a short-lived token your own server signs with your feedback portal's widget secret (scheme portal_token). It exists because no credential that reaches a browser can be kept secret, so the page carries a signed claim about who is submitting rather than a key. On that credential the identity is taken from the token's claims (sub, email, name, company, iss) and owner, submitterId, issuer, submitterName, anonymous and company in the BODY are rejected with 422 — the page is under the submitter's control and the token is not. The token is good for one hour from iat whatever its exp says, covers as many submissions as the person makes inside that hour, and is not single use. A 401 with error: "token_expired" means fetch a new one and retry; error: "token_invalid" will never succeed on retry.
Before you build the signing half, a portal can issue a development key (Authorization: Bearer cwk_dev_…) which is sent as-is with the identity fields in the body, accepted only from an origin the administrator registered as development. Everything it creates is marked as development in the portal's user list. It is a different key from the production one, so what you paste into a page while building can never sign a real submission.
What to send, and how to know it is right. GET /feedback_portal/{portalId}/widget/{widgetId}/config returns the widget's categories and the portal's own fields with their required flags, so a form can be rendered from the portal's definition and a missing field caught before posting rather than by a rejection here.
A stale importanceId does not cost you the submission. On either widget credential, an importance id the portal no longer has — an administrator can delete one while your page is open — is dropped and the portal's default applied, rather than refused. On x-api-key it is a 422 listing the valid ids, because that caller can re-read them and retry.
No cookie is set and no Craft session exists, on this call or on the config read. Worth stating as a property rather than an implementation detail: nothing about the person submitting is stored in their browser by Craft, which is usually the question a customer's privacy review asks first.
Request
- Base URLhttps://api.craft.io
- URLhttps://api.craft.io/feedback_portal/{portalId}/plain_feedback
- AuthAPI key in header x-api-key
Path parameters
Request body
Example request
{
"owner": "user@example.com",
"widgetId": "2305843010139571300",
"importanceId": "Critical",
"anonymous": true,
"submitterId": "user_84213",
"issuer": "billing-app",
"submitterName": "Jane Doe",
"sourceUrl": "https://app.acme.com/reports?tenant=acme-eu&view=board",
"attachmentIds": [
"2305843010342823571"
]
}Response
Create a plain feedback
Changes
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the new optional request property
- info
added the non-success response with the status
- info
added the optional property
to the response with the status - info
added the optional property
to the response with the status - info
added the optional property
to the response with the status
- info