Fac-360
Complaint book

Record this company's answer to a complaint

The act that discharges the obligation: the provider has fifteen working days to answer, and this is the record that they did. Its own scope, because answering is the provider speaking on the record and not a read with a side effect. ONE answer per complaint: posting again CORRECTS the text and reports corrected: true, and respondedAt still reports the FIRST answer — a correction does not move the date the obligation was discharged on, or a late answer could be made to look punctual. The complaint itself is never editable by anyone, including this company: what a consumer filed is the record, and the answer goes beside it rather than over it.

POST
/api/v2/complaints/{trackingCode}/response

The act that discharges the obligation: the provider has fifteen working days to answer, and this is the record that they did. Its own scope, because answering is the provider speaking on the record and not a read with a side effect. ONE answer per complaint: posting again CORRECTS the text and reports corrected: true, and respondedAt still reports the FIRST answer — a correction does not move the date the obligation was discharged on, or a late answer could be made to look punctual. The complaint itself is never editable by anyone, including this company: what a consumer filed is the record, and the answer goes beside it rather than over it.

Authorization

bearerAuth
AuthorizationBearer <token>

Tenant-bound, scoped and expiring Apifact credential. Migrated legacy credentials are accepted only on deprecated v1 writes and tenant-scoped v2 read, poll and download routes. Each operation names the single scope it requires in x-required-scope; the scope array of the security requirement itself is empty because OpenAPI 3.0 requires it to be for a non-oauth2 scheme.

In: header

Path Parameters

trackingCode*string

The code the consumer received when they filed.

Match^[RQ]-[0-9]{4}-[0-9]{6}$

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

Response Body

application/json

application/json

application/json

application/json

application/json

curl -X POST "https://example.com/api/v2/complaints/string/response" \  -H "Authorization: Bearer apf_v2_tu_credencial" \  -H "Content-Type: application/json" \  -d '{    "body": "Revisamos el caso y le damos la razon: el servicio no se presto en la fecha acordada por un error de nuestra programacion. Devolvemos el importe cobrado a la misma tarjeta, con un plazo de siete dias habiles para que su banco lo refleje, y le llamaremos para confirmarlo."  }'
{  "schemaVersion": "2.0",  "requestId": "d385ab22-0f51-4b97-9ecd-b8ff3fd4fcb6",  "trackingCode": "string",  "respondedAt": "2019-08-24T14:15:22Z",  "corrected": true}

File a complaint with your own credential POST POST

The door for a client that has its own server: your form posts to you, you post here. Preferred over the credential-less public route whenever you can do it, because the tenant then comes from the credential like everything else in this API. It writes through the SAME implementation the public door uses, so the correlativo, the checks and the record are identical and only source differs — PUBLIC there, API here. NO Idempotency-Key, and this is the one route in v2 where a repeat can duplicate. It is accepted deliberately: a duplicate complaint burns no correlativo, reaches no SUNAT and creates no fiscal fact, and the public twin of this act is a browser that has no key to offer — two doors onto one book that de-duplicated differently would be worse than neither doing it. Refuses with 409 if the company has not minted its book yet.

File a complaint or a grievance into a company's complaint book POST POST

The public door of the Libro de Reclamaciones. NO CREDENTIAL: the caller is a consumer, not an integrator, and has no account here. THE BOOK IDENTIFIER IS THE CAPABILITY. It is an opaque UUID we mint for a company and can rotate; it lets its holder WRITE ONE COMPLAINT into one book and nothing else. There is no GET under /public/v1: a leaked identifier cannot read a complaint, cannot reveal whose book it is, and cannot reach anything else on this hostname. EVERY UNUSABLE BOOK ANSWERS THE SAME 404. Unknown identifier, retired book, company no longer active: one code, one message. Distinguishing them would answer 'is this business a client of yours?' for anyone willing to iterate. CORS IS ALLOWED HERE AND NOWHERE ELSE ON THIS HOSTNAME, because the form lives on the client's own domain. `Access-Control-Allow-Origin: *` with NO `Access-Control-Allow-Credentials`, so a browser will not attach the console session cookie to these requests and will not expose a response to a script that tried. RATE LIMITED PER IP, ten entries per sixty seconds, keyed on the address Cloudflare saw. Per IP and not per book on purpose: a per-book bucket would let one flood close a company's legal complaint form for everybody else. THE RECEIPT IS NOT THE BOOK IDENTIFIER. The response carries a tracking code issued per company and per year, which is what the consumer quotes to follow up.