Skip to content
Documentation
pozyskajpacjentaDocs

API referenceFeedback

Send feedback

POST/api/v1/feedback

Since
1.6.0
Auth
Bearer key
operationId
sendFeedback

Sends a remark about the clinic's site or about the API to the platform team, from your frontend's backend or as a browser error report it forwards. Besides the per-minute limit there is a limit of 20 remarks per hour per clinic, counted separately for each source (429 feedback_rate_limited with Retry-After). E-mail addresses, phone numbers, PESEL-like numbers and tokens in addresses (e.g. a patient's /wizyta/<token> link) are removed before storing.

Request

Send the clinic's key in Authorization: Bearer (see API keys).

Body application/json

The remark as JSON.

  • messagestringrequired

    The remark, 3 to 4000 characters.

  • kindstring

    uwaga: content or look. potrzeba_api: something your frontend needs from the API. blad: something does not work.

    One of uwagapotrzeba_apiblad

  • categorystring

    Area: tresc (content), wyglad (look), funkcja (a feature), backend, inne (other).

    One of trescwygladfunkcjabackendinne

  • sourcestring

    site: the clinic site's backend. client_error: a browser error report your backend forwards. One more value is reserved for the platform team's own tooling.

    One of siteclient_error

  • pageUrlstring

    The page the remark is about: an absolute address or a path from /.

  • viewportstring

    Viewport of the report, e.g. 1440x900.

  • selectorstring

    CSS selector of the element the remark is about.

  • reporterstring

    Who reports it (e.g. a staff member's name). Kept with the remark, left out of what the platform team sees.

  • metaobject

    Flat object, up to 30 keys and 4000 characters of JSON: values are text (up to 500 characters), numbers, true/false or null. E.g. userAgent, appVersion.

curl -X POST "https://app.pozyskajpacjenta.pl/api/v1/feedback" \
  -H "Authorization: Bearer $PP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "kind": "blad",
    "category": "funkcja",
    "message": "Na telefonie przycisk rezerwacji zasłania stopkę strony zabiegu.",
    "pageUrl": "https://wzorcowa.pozyskajpacjenta.pl/zabiegi/implanty?utm_source=google",
    "viewport": "390x844",
    "selector": "[data-cta=sticky-booking]"
  }'
import { PozyskajPacjentaClient } from "@pozyskajpacjenta/sdk";

const client = new PozyskajPacjentaClient({
  apiKey: process.env.PP_API_KEY ?? "",
  baseUrl: "https://app.pozyskajpacjenta.pl",
});

const { id, redacted } = await client.sendFeedback({
  kind: "blad",
  category: "funkcja",
  message: "Na telefonie przycisk rezerwacji zasłania stopkę strony zabiegu.",
  pageUrl: "https://wzorcowa.pozyskajpacjenta.pl/zabiegi/implanty?utm_source=google",
  viewport: "390x844",
  selector: "[data-cta=sticky-booking]",
});
<?php
$body = array(
    'kind'     => 'blad',
    'category' => 'funkcja',
    'message'  => 'Na telefonie przycisk rezerwacji zasłania stopkę strony zabiegu.',
    'pageUrl'  => 'https://wzorcowa.pozyskajpacjenta.pl/zabiegi/implanty?utm_source=google',
    'viewport' => '390x844',
    'selector' => '[data-cta=sticky-booking]',
);

$response = wp_remote_post(
    'https://app.pozyskajpacjenta.pl/api/v1/feedback',
    array(
        'headers' => array(
            'Authorization' => 'Bearer ' . getenv( 'PP_API_KEY' ),
            'Content-Type'  => 'application/json',
        ),
        'body'    => wp_json_encode( $body ),
        'timeout' => 10,
    )
);
if ( is_wp_error( $response ) ) {
    error_log( $response->get_error_message() );
    return;
}
$status = wp_remote_retrieve_response_code( $response );
$data   = json_decode( wp_remote_retrieve_body( $response ), true );

Response

201The remark was accepted.

  • idstringrequired

    Id of the remark, fb_…

  • statusstringrequired

    new: accepted; it is passed on to the platform team.

    One of newsyncedignored

  • redactedstring[]

    Only when something was removed before storing: email, phone, pesel.

    One of emailphonepesel

Remark accepted

{
  "id": "fb_YRNxN-wdvwgXufTq",
  "status": "new"
}

Accepted after removing an e-mail and a phone number

{
  "id": "fb_m3-ehVwoPDTP7PMR",
  "status": "new",
  "redacted": [
    "email",
    "phone"
  ]
}

Errors

StatuscodeWhen
400invalid_jsonThe body is not JSON
400invalid_bodyA field failed validation
401No Authorization header
401Unknown or rotated key
429feedback_rate_limitedThe hourly limit for this source is used up
429Over 120 requests in this minute

Branch on the status and code, never on the Polish error text. All statuses in Errors.

400 · The body is not JSON
{
  "error": "invalid JSON",
  "code": "invalid_json"
}
400 · A field failed validation
{
  "error": "category: Invalid option: expected one of \"tresc\"|\"wyglad\"|\"funkcja\"|\"backend\"|\"inne\"",
  "code": "invalid_body"
}
401 · No Authorization header
{
  "error": "missing Authorization: Bearer <klucz z panelu Ustawienia>"
}
401 · Unknown or rotated key
{
  "error": "invalid key"
}
429 · The hourly limit for this source is used up
{
  "error": "przekroczono limit 20 zgłoszeń na godzinę",
  "code": "feedback_rate_limited"
}
429 · Over 120 requests in this minute
{
  "error": "przekroczono limit 120 zapytań/min"
}

Rate limit

  • 120 requests per minute per key, shared by every endpoint.
  • 20 remarks per hour per clinic, counted separately for each source.
  • Every response to a valid key carries RateLimit-Remaining and RateLimit-Reset; see Rate limits.

SDK method

client.sendFeedback(input: FeedbackInput): Promise<FeedbackCreated>

Throws ApiError 429 with code: "feedback_rate_limited" over the hourly limit.

The TypeScript tab above uses it. Install and errors: TypeScript SDK.