Give customers AI answers with checked sources and optional word-for-word quotes.
Your server sends a customer's question. Ask PCIFIC reads your documents and returns a short answer with sources and optional quotes. You build the question box. Citations always point to a real source Ask has read, and quotes are checked word for word. Ask is instructed to stay within its sources, but a sentence can occasionally add general advice that is not in them.
Ask PCIFIC supports English only; other languages are not supported yet.
| Who asks | Example questions | Documents to add | Item to send |
|---|---|---|---|
| A buyer on a shop listing | Can I return this if I change my mind? When will it arrive? | Returns policy, delivery policy, buyer protection page | The listing: its id, title and details such as condition |
| An insurance customer | Does my cover include water damage? How do I make a claim? | Policy wording (PDF or Word), claims guide | The cover being looked at, for example type policy and a title such as Home contents, Standard |
| A guest on a rental page | Is there a deposit? Can I cancel for free? | House rules, cancellation policy | The property or booking with its details |
| A visitor on a support or help page | How do I reset my password? | Your help pages, each added as a web address so they are checked daily | Nothing |
| A business customer | What warranty comes with this part? Is there a minimum order? | Trade terms, delivery terms, warranty terms | The product, found by its id from your own system (item lookup) |
The same tool works for every row: the documents and the item change, nothing else does. An item can be anything a customer is looking at: a listing, a product, a policy, a property or a booking.
Answer and block text contain no citation tags. Each text block has a separate sources list naming the document section, listing or web page it used. Source number starts at 1 for each answer; show that number beside the relevant block. Quote blocks refer to sourceNumber. Internal tag, documentId and itemId are for your server, not buyer-facing labels. The AI is instructed to put your shop documents before seller wording on policy questions and to use supplied sources for facts about the listing, seller, deal and shop. Ask can still explain general concepts neutrally; judgments about a particular seller or deal need to be stated in a document or the listing.
These steps use a test key in $PCIFIC_TEST_KEY with the documents, ask-pcific and settings permissions. The ids and times in the answers are examples, yours will differ. These example answers show successful source use; other answers can occasionally include general advice absent from their sources.
Document uploads share a bounded allowance across the API and dashboard: eight uploads and 64 MiB of reserved input per server, with two uploads and 22 MiB per business across all shops and keys. Web-address downloads and refreshes share this allowance; busy background refreshes stay due for the next run. PCIFIC reserves Content-Length before reading; a missing length reserves the full 10 MiB plus 64 KiB request allowance, and real streamed bytes are checked. PDF conversion waits at most two seconds for a reader. A 429 DOCUMENT_UPLOAD_LIMIT means your business is at its share; 503 DOCUMENT_UPLOAD_BUSY means server capacity is full or the PDF wait ended. Both include Retry-After: 20. Try the upload again after 20 seconds. A 408 DOCUMENT_UPLOAD_TIMEOUT means the body did not finish arriving within 20 seconds: check your connection and retry, or split a large file. These limits also cover Word, HTML, Markdown and text files, JSON documents and replacements.
Headings written as # Heading become sections. The answer is 201 (created) and the document is live straight away, because reviewMode is automatic by default.
curl -X POST https://business.pcific.ai/api/v1/documents \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"title":"Returns policy","text":"# Who can return\nYou can return any item within 30 days of delivery.\n\n# Refunds\nRefunds go back to your original payment method within 5 working days of us getting the item."}'{
"id": "9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11",
"title": "Returns policy",
"source": "text",
"url": null,
"fileName": null,
"status": "live",
"published": true,
"liveVersion": {
"id": "e07a4c19-6b2d-4f38-a1c5-83d9b0f2c764",
"createdAt": "2026-10-19T09:00:00.512Z",
"characters": 173,
"approvedAt": "2026-10-19T09:00:00.512Z",
"approvedBy": null
},
"waitingVersion": null,
"lastCheck": null,
"lastChangedAt": null,
"createdAt": "2026-10-19T09:00:00.512Z",
"updatedAt": "2026-10-19T09:00:00.512Z",
"warnings": []
}You can instead give a web address, which PCIFIC copies now and checks daily, or upload a file. See Documents below. A document added from a web address also lets answers show a page link to it.
curl -X POST https://business.pcific.ai/api/v1/ask-pcific \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Can I return this coat if I change my mind?","quotes":true,"item":{"type":"listing","title":"Wool coat, navy, size M","details":{"condition":"Used, good","status":"Available"}}}'{
"conversationId": "4b0c2d7e-5a3f-4c1e-9b7a-2e8d6f1a0c35",
"status": "answered",
"answer": "Yes. You can return it within 30 days of delivery.\n\n\"You can return any item within 30 days of delivery.\"",
"blocks": [
{
"type": "text",
"text": "Yes. You can return it within 30 days of delivery.",
"sources": [
{
"number": 1,
"tag": "d1.1",
"type": "document",
"documentId": "9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11",
"document": "Returns policy",
"section": 1,
"heading": "Who can return"
}
]
},
{
"type": "quote",
"text": "You can return any item within 30 days of delivery.",
"sourceNumber": 1,
"documentId": "9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11",
"document": "Returns policy",
"section": 1,
"heading": "Who can return"
}
],
"sources": [
{
"number": 1,
"tag": "d1.1",
"type": "document",
"documentId": "9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11",
"document": "Returns policy",
"section": 1,
"heading": "Who can return"
}
],
"quoteAvailable": true,
"supportLink": null,
"aiNotice": "Generated with our company AI. Please verify the information before relying on it.",
"release": "2.0.0",
"warnings": []
}Show the blocks in order: a text block as a paragraph, a quote block as a quote with its document and section, and a page block as a card or button that opens the link. Keep conversationId to carry on the chat.
Send the conversationId from the last answer with the customer's next question. The AI then sees the last 8 turns of the chat. Leave it out to start a new chat.
curl -X POST https://business.pcific.ai/api/v1/ask-pcific \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"How long do refunds take?","conversationId":"4b0c2d7e-5a3f-4c1e-9b7a-2e8d6f1a0c35"}'curl -X POST https://business.pcific.ai/api/v1/ask-pcific \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"question":"Do you ship to Norway?"}'{
"conversationId": "4b0c2d7e-5a3f-4c1e-9b7a-2e8d6f1a0c35",
"status": "not_covered",
"answer": "I couldn't find the answer to that in our information. Please contact our support team.",
"blocks": [
{
"type": "text",
"text": "I couldn't find the answer to that in our information. Please contact our support team.",
"sources": []
}
],
"sources": [],
"quoteAvailable": false,
"supportLink": "https://example.com/help",
"aiNotice": "Generated with our company AI. Please verify the information before relying on it.",
"release": "2.0.0",
"warnings": []
}Show the fallback message and offer supportLink. This is not an error: the status is 200. supportLink is null on an answered answer, and it is the support link you set in the settings.
curl -X GET https://business.pcific.ai/api/v1/ask-pcific/unanswered?limit=20 \
-H "Authorization: Bearer $PCIFIC_TEST_KEY"{
"questions": [
{
"question": "Do you ship to Norway?",
"reason": "No document says which countries we deliver to",
"askedAt": "2026-10-19T09:14:03.221Z"
}
]
}Newest first. Add a document that covers each one and the next customer gets an answer. An unanswered question is kept for 30 days, and not at all while Ask PCIFIC is on the True ZDR privacy tier (see Monitoring and privacy).
curl -N -X POST https://business.pcific.ai/api/v1/ask-pcific \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-H "Accept: text/event-stream" \
-d '{"question":"Can I return this coat if I change my mind?","quotes":true,"item":{"type":"listing","title":"Wool coat, navy, size M","details":{"condition":"Used, good","status":"Available"}}}'event: text
data: {"type":"text","text":"Yes. You can return it within 30 days of delivery.","sources":[{"number":1,"tag":"d1.1","type":"document","documentId":"9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11","document":"Returns policy","section":1,"heading":"Who can return"}]}
event: quote
data: {"type":"quote","text":"You can return any item within 30 days of delivery.","sourceNumber":1,"documentId":"9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11","document":"Returns policy","section":1,"heading":"Who can return"}
event: done
data: {"conversationId":"4b0c2d7e-5a3f-4c1e-9b7a-2e8d6f1a0c35","status":"answered","answer":"Yes. You can return it within 30 days of delivery.\n\n\"You can return any item within 30 days of delivery.\"","sources":[{"number":1,"tag":"d1.1","type":"document","documentId":"9c1f5b0e-3d6a-4a52-8f55-2b7d1c0a4e11","document":"Returns policy","section":1,"heading":"Who can return"}],"quoteAvailable":true,"supportLink":null,"aiNotice":"Generated with our company AI. Please verify the information before relying on it.","release":"2.0.0","warnings":[]}| Event | What it carries |
|---|---|
text | A paragraph of the answer, with its sources. The same object as a text block. |
quote | A document's exact words with the document, section and heading they come from. |
page | A document's title and link, to show as a card or button. |
done | The finished answer: conversationId, status, answer, sources, supportLink, aiNotice, release and warnings. |
error | {error, code, tryThis}: the same three parts as any error. It always ends the stream. |
a comment line | A line starting with a colon arrives every 15 seconds while the AI works, to keep the connection open. Ignore it. |
POST /api/v1/ask-pcific takes JSON, at most 16 KB. A field it does not know is ignored and named in warnings, so a typo shows up there rather than failing the question.
| Field | Type | Required | What it is |
|---|---|---|---|
question | string | Yes | The customer's question, 1 to 1,500 characters. Ask PCIFIC supports English only; other languages are not supported yet. |
quotes | boolean | No | Optional, false by default. Request at least one verified document quote when a document supports the answer. If the AI omits it, PCIFIC uses the first paragraph of a cited section. quoteAvailable tells you whether the answer includes a verified quote; no internal message is added to the buyer answer. Without true, quote blocks are optional. |
modelTier | string | No | standard (the default) or ultra-fast. Ultra Fast answers in about half a second instead of several, and a live use spends more credits: the Credits page in your dashboard shows how many. A use is charged as Ultra Fast only when Ultra Fast answered the whole request; otherwise Standard answers and it is charged as Standard. A business on its own AI key is answered by its own model. null is the same as leaving it out. |
conversationId | string | No | Leave it out, or send null, to start a new chat. Send the one from the last answer to carry on, so the AI sees the last 8 turns. |
buyer | object | No | The asking buyer, supplied by your shop server. Only accountId is accepted inside buyer; unknown keys return ASK_ACCOUNT_ID_INVALID, naming the key and what to send instead. null is the same as leaving it out. |
buyer.accountId | string | No | Opaque account id, never a name or username. 1 to 128 ASCII letters, digits, dots, colons, underscores or hyphens. Compared only in the backend, never sent to the AI. Sent to item lookup as the buyerAccountId query parameter, including get_item. null is the same as leaving it out. |
item | object | No | The item the customer is looking at: a listing, product, policy, property or booking. Only item.id is needed when item lookup is set up. null is the same as leaving it out. |
item.id | string | integer | No | Your own id for the item, text or a whole number, 1 to 128 characters, for example "coat-8841" or 8841. Requires listing lookup; otherwise the request is refused with ASK_ITEM_LOOKUP_NOT_CONFIGURED before AI work. A number is read as its digits. With lookup set up, PCIFIC looks the item up by this id and ignores every other item field. null is the same as leaving it out. |
item.type | string | No | Any word for what it is, such as listing or booking. Up to 40 characters. null leaves it out. |
item.title | string | No | Up to 300 characters. null leaves it out. |
item.url | string | No | Up to 2,000 characters. The AI sees it. PCIFIC never opens it. null leaves it out. |
item.reservedForAccountId | string | No | Opaque account id of the buyer holding the reservation, never a name or username. Same 1 to 128 character rules as buyer.accountId. Matching ids mean reserved for you; different ids mean unavailable, reserved by another buyer. An explicit null reservedForAccountId means not reserved. Otherwise, if either id is missing, ownership cannot be confirmed. Only the comparison result reaches the AI; neither id is returned. With neither id establishing a reservation, an explicit Available or Not reserved status means not reserved. |
item.price | object | No | Optional price, using the shared Orbit and Safeguard money format. For example {amount: 9575, currency: GBP} means £95.75 GBP. With lookup, return price at the top level of the lookup JSON. Only objects with exactly amount and currency use this contract; other shapes, including legacy {value, currency} objects, stay ordinary listing details. |
item.price.amount | integer | Yes | Nonnegative whole number in the currency's smallest unit, such as pence or cents. Never a decimal or text. Yen has no smaller unit. |
item.price.currency | string | Yes | Three letter currency code in capitals, for example GBP, USD or JPY. Ask displays the amount with that currency and never converts it. |
item.details | object | No | Listing facts a customer might ask about, as names and values. Include item.details.status as text stating current availability. Reservation ownership comes only from comparing buyer.accountId with item.reservedForAccountId, never from seller wording. With item lookup, return status, reservedForAccountId and price at the top level of the lookup JSON. Seller wording cannot override your shop policy documents. Up to 60 entries. Each value is plain: text up to 2,000 characters, a number, true, false or null. The names are your own and are passed on exactly as sent. null for the whole object is the same as leaving it out. |
item.details.{name} | string | number | boolean | No | One listing fact under your own name for it, such as condition or status. Text up to 2,000 characters, a number, true, false or null. |
Send item.details.status with the current availability. Send buyer.accountId for the asking buyer and item.reservedForAccountId for the reservation holder, as opaque account ids, never names or usernames. The backend compares them and only sends the result to the AI: matching ids mean reserved for you; different ids mean unavailable, reserved by another buyer; an explicit null reservedForAccountId means not reserved; otherwise either id missing means ownership cannot be confirmed. An explicit Available or Not reserved status with no reservation holder means not reserved. Neither id reaches the AI. With item lookup, Ask sends buyer.accountId as the buyerAccountId query parameter, including get_item; return status, reservedForAccountId and price at the top level of the lookup JSON. Only price objects with exactly amount and currency use the structured contract. Other shapes, including legacy {value, currency} objects, stay ordinary listing details. If a lookup field is invalid, correct the named field in your configured lookup response and test it again. Never infer reservation ownership from seller wording. Optional item.price uses {amount: 9575, currency: GBP} for £95.75 GBP, the same money format as Orbit and Safeguard. Use a nonnegative whole number in the smallest unit, such as 4500 pence for £45, and a three letter currency code in capitals. Decimal points, exponents and text amounts are refused with 400 ASK_PRICE_INVALID. If you have set up item lookup and send item.id, PCIFIC looks the item up itself and ignores every other item field you sent, so a customer cannot change a price. A warning says so. If you send item.id without item lookup, the request is refused with 400 ASK_ITEM_LOOKUP_NOT_CONFIGURED before AI work. Set up item lookup, or leave item.id out and send the listing details instead.
| Field | Type | Required | What it is |
|---|---|---|---|
conversationId | string | Yes | The chat. Send it with the customer's next question. null when you have switched chats off. |
status | string | Yes | answered, or not_covered when nothing you wrote covered the question. |
answer | string | Yes | The whole answer as plain text, without citation tags. It can occasionally add general advice absent from its sources. Quotes are in quote marks and pages are written "title: link". |
blocks | object[] | Yes | The answer in reading order. Only in the JSON answer, not in a stream. Each has a type: text (a paragraph with its sources), quote (the document's exact words with their document and section) or page (a document's title and link). |
sources | object[] | Yes | Every cited source across all blocks, each once. number starts at 1 for each answer; display it beside the relevant block. type is document, item or web. Internal tag, documentId and itemId remain available for your server; use number as the buyer-facing label. Citations identify real sources the AI read, without checking support for each sentence. Text blocks have their own sources; quote blocks use sourceNumber. |
quoteAvailable | boolean | Yes | Whether this answer includes a verified document quote. False adds no message to the buyer answer. |
supportLink | string | Yes | Your support link, only when status is not_covered. Otherwise null. |
aiNotice | string | Yes | The notice to show beside the answer, from your shop settings. null when you chose none. |
modelTier | object | Yes | Which tier answered: {requested, handledBy, message}. |
modelTier.requested | string | Yes | standard or ultra-fast, as the request asked. |
modelTier.handledBy | string | Yes | The tier that answered the whole request: standard, ultra-fast, or byo when your own AI key answered. A use is charged as Ultra Fast only when this is ultra-fast. |
modelTier.message | string | Yes | Why handledBy differs from requested, else null. |
release | string | Yes | The Ask PCIFIC release that answered. Always "2.0.0" today. |
warnings | string[] | Yes | Fields you sent that PCIFIC ignored, and why. |
| type | What it is | Fields |
|---|---|---|
text | A paragraph with tag-free text and a separate list of numbered sources. | type, text, sources |
quote | The document's exact words. Spacing, curly quotes, dashes and bold or italic marks do not count as differences, and "..." in a quote may skip text. | type, text, sourceNumber, documentId, document, section, heading |
page | A document's title and link, to show as a card or button. Only documents added from a web address have a page. | type, documentId, title, url |
| type | What it is | Fields |
|---|---|---|
document | A part of one of your documents. section and heading are left out when the tag names the whole document, like [d1]. | number, tag, type, documentId, document, section, heading |
item | The item the customer is looking at (tag item), or another item the AI looked up (tag i1, i2...). | number, tag, type, itemId |
web | A web page the search found (tag w1, w2...). Only when web search is on. | number, tag, type, title, url |
Add the documents you want Ask PCIFIC to use. An owner or admin can manage them on the dashboard Documents page, or your own system can do it over the API with a key that has the documents permission.
| Way | What you send |
|---|---|
| Paste text | POST /api/v1/documents as JSON {"title": "Returns policy", "text": "..."}. The title is required. |
| Give a web address | JSON {"url": "https://example.com/returns"}. The title is optional and defaults to the page's own title. PCIFIC copies it now and checks it daily. |
| Upload a file | multipart/form-data with the file in a part named file, and optionally a title. A PDF, Word (.docx), web page (.html), Markdown (.md) or text (.txt) file, up to 10 MB. The title defaults to the file name. |
curl -X POST https://business.pcific.ai/api/v1/documents \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://example.com/returns"}'curl -X POST https://business.pcific.ai/api/v1/documents \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-F file=@warranty.docx \
-F title="Warranty"| Field | Type | Required | What it is |
|---|---|---|---|
id | string | Yes | The document. |
title | string | Yes | Its title. |
tags | string[] | Yes | Optional document labels, returned as [] when none are set. Up to 5 different lowercase words, each 1 to 24 letters (a to z). |
source | string | Yes | How it was added: text, file or url. |
url | string | Yes | The web page, for a url document. |
fileName | string | Yes | The cleaned uploaded name, for a file document. Folders, control characters and .. are removed. If nothing remains, PCIFIC uses a document name based on the Content-Type. |
status | string | Yes | live (it is answering), waiting (only a version waiting for approval, so it does not answer yet), not_live (its only version was rejected), or unpublished (kept but not used for answers). |
published | boolean | Yes | false keeps the document and versions but stops Ask PCIFIC using it. |
liveVersion | object | Yes | {id, createdAt, characters, approvedAt, approvedBy} of the approved version, or null. approvedAt is UTC ending in Z. approvedBy is {name, role}, or null for an automatic approval. |
waitingVersion | object | Yes | The same for a version waiting for an owner or admin to approve it, or null. |
lastCheck | object | Yes | Web page documents only, otherwise null: {at, ok, error, tryThis}. ok is false when the last read failed, and the last good version keeps answering. |
lastChangedAt | string | Yes | Website documents only, otherwise null. UTC time when changed text was last saved, including an update waiting for approval. Unchanged checks leave it alone. |
createdAt | string | Yes | When it was added. |
updatedAt | string | Yes | When it last changed. |
liveVersion.id | string | Yes | The version. |
liveVersion.createdAt | string | Yes | When it was made. |
liveVersion.characters | integer | Yes | Its length once converted to text. |
liveVersion.approvedAt | string | Yes | When it was approved, in UTC ending in Z. Always null for a waiting version. |
liveVersion.approvedBy | object | Yes | Who approved it, or null for an automatic approval. Always null for a waiting version. |
liveVersion.approvedBy.name | string | Yes | The name of the person who approved it, or Former member when they have left the business. |
liveVersion.approvedBy.role | string | Yes | Their role when they approved it, such as owner or admin. null when it was not recorded. |
waitingVersion.id | string | Yes | The version. |
waitingVersion.createdAt | string | Yes | When it was made. |
waitingVersion.characters | integer | Yes | Its length once converted to text. |
waitingVersion.approvedAt | string | Yes | When it was approved, in UTC ending in Z. Always null for a waiting version. |
waitingVersion.approvedBy | object | Yes | Who approved it, or null for an automatic approval. Always null for a waiting version. |
waitingVersion.approvedBy.name | string | Yes | The name of the person who approved it, or Former member when they have left the business. |
waitingVersion.approvedBy.role | string | Yes | Their role when they approved it, such as owner or admin. null when it was not recorded. |
lastCheck.at | string | Yes | When PCIFIC last read the page, in UTC. |
lastCheck.ok | boolean | Yes | false when the last read failed. The last good version keeps answering. |
lastCheck.error | string | Yes | Why the last read failed, or null when it worked. |
lastCheck.tryThis | string | Yes | What to try next when the last read failed, or null when it worked. |
No API key, test or live, can approve or reject a waiting version. The key sits on your servers, and a leaked one must not be able to put new policy wording in front of customers. POST /api/v1/documents/{id}/versions/{versionId} is for the dashboard only, and an API key that calls it gets 403 DOCUMENT_DECISION_NEEDS_DASHBOARD. Use GET on a document to see its waiting version, and tell an owner or admin to decide.
Text sent as JSON and uploaded UTF-8 text or Markdown is stored exactly as given, including spaces and trailing newlines. Download a version with GET /api/v1/documents/{id}/versions/{versionId} and read markdown to get that same text. Other file formats are converted to Markdown.
Uploaded file names are cleaned before they are stored or returned: folder names, control characters and .. are removed. If nothing remains, PCIFIC uses a document name based on the file's Content-Type.
Use optional tags to organise documents, for example returns or shipping. Send tags as a JSON array of up to 5 different lowercase words, each 1 to 24 letters (a to z). With a file upload, send the same JSON array in a part named tags. Tags appear in every document view; documents without tags return [].
Set tags when creating or replacing content. Leaving tags out keeps them on replacement; [] clears them. To edit only tags, send {"tags": ["returns", "shipping"]} to PUT /api/v1/documents/{id}/tags. This keeps the source, text and approval status. On the dashboard, add tags with a document or choose Edit tags, then filter by tag and by live, waiting for approval, unpublished or not live. A document with a waiting replacement appears in both Live and Waiting for approval.
| Address | What it does |
|---|---|
GET /api/v1/documents | Every document, and limits: {documents: {used, max}, characters: {used, max}}. |
POST /api/v1/documents | Add one. Answers 201 with the document and warnings. |
GET /api/v1/documents/{id} | One document with its sections (the live version's, or the waiting one's if nothing is live) and its versions. |
PUT /api/v1/documents/{id}/content | Replace its content with new text, a web address or a file. title is optional and keeps the old one. There is no PATCH: to rename a document, send its content again with a new title. |
PUT /api/v1/documents/{id}/tags | Set tags without replacing content. Send {"tags": ["returns"]}, or {"tags": []} to clear them. |
POST /api/v1/documents/{id}/refresh | Read a web page document now. |
POST /api/v1/documents/{id}/unpublish | Stop using it in answers, keeping its id and all saved versions. |
POST /api/v1/documents/{id}/publish | Publish again with its same id and last approved text. Waiting versions still need approval. |
GET /api/v1/documents/{id}/versions/{versionId} | One version's full text (markdown) and sections. |
POST /api/v1/documents/{id}/versions/{versionId} | Approve or reject a waiting version. Dashboard only: every API key is refused with 403. |
DELETE /api/v1/documents/{id} | Delete a document and every version of it. |
| Field | Type | Required | What it is |
|---|---|---|---|
id | string | Yes | The version. |
status | string | Yes | live, waiting, rejected or replaced. |
createdAt | string | Yes | When it was made. |
characters | integer | Yes | Its length once converted to text. |
approvedAt | string | Yes | When it was approved, in UTC ending in Z. null if never approved or the earlier approval time was not recorded. |
approvedBy | object | Yes | {name, role} of the owner or admin who approved it, or null for an automatic approval. |
approvedBy.name | string | Yes | The name of the person who approved it, or Former member when they have left the business. |
approvedBy.role | string | Yes | Their role when they approved it, such as owner or admin. null when it was not recorded. |
GET and PUT /api/v1/ask-pcific/settings. A PUT changes only the fields you send. null clears fallbackMessage and supportLink; voice: null uses your shop voice. A live key can read these but never change them: use a test key with the settings permission, or the dashboard. The full list of every tool's settings is on the Shop configuration page.
| Field | Type | Required | What it is |
|---|---|---|---|
enabled | boolean | No | false refuses every question with ASK_TURNED_OFF. Default true. |
webSearch | boolean | No | Whether the AI may search the web for general facts. Default true. false limits its supplied sources to your documents and the item. |
reviewMode | string | No | automatic (the default) puts a changed document live at once. approve_first holds each new version until an owner or admin approves it. Only an owner or admin can change this setting on the dashboard Documents page; API keys cannot change it. |
fallbackMessage | string | No | What a not_covered answer says, up to 500 characters. GET shows the standard message when you have not set one. |
supportLink | string | No | An https:// or mailto: link, up to 2,000 characters. Sent back with a not_covered answer. |
voice | string | No | Ask PCIFIC's voice: standard, warm, upbeat, formal, concise or reassuring. null uses your shop's voice. |
keepChats | boolean | No | Whether a chat is kept so follow-up questions work. Default true. false means each question stands alone and nothing about the chat is stored. |
curl -X PUT https://business.pcific.ai/api/v1/ask-pcific/settings \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"supportLink":"https://example.com/help"}'{
"enabled": true,
"webSearch": true,
"reviewMode": "approve_first",
"fallbackMessage": "I couldn't find the answer to that in our information. Please contact our support team.",
"supportLink": "https://example.com/help",
"voice": null,
"keepChats": true,
"warnings": []
}The listing always comes from your own systems, never from the customer's page. Anything on a page can be edited in the customer's browser, so a question box that reads the listing from the page would let anyone get an answer about a price or condition you never set. Set up item lookup once and send only the item's id with each question. PCIFIC reads the listing from your own listings address at the moment the customer asks, so the answer matches what the customer sees, and PCIFIC never stores your listings. Your address answers as it already does, and every field it returns reaches the AI exactly as you named it. If your server sends the item's details with the question instead, read them from your own system at that moment, never from the customer's page.
With item lookup you give PCIFIC an address of yours that answers one item as JSON, and then you send the item id and optional buyer.accountId. The lookup receives buyerAccountId as a query parameter, for example /items/coat-8841?buyerAccountId=opaque-buyer-1. PCIFIC fetches the current details itself, so they are always up to date and the customer cannot change them. The AI can also look up another item by its id when the customer names one.
curl -X PUT https://business.pcific.ai/api/v1/ask-pcific/item-source \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://api.example.com/items/{id}","headerName":"Authorization","headerValue":"Bearer your-items-api-key"}'{
"url": "https://api.example.com/items/{id}",
"headerName": "Authorization"
}curl -X POST https://business.pcific.ai/api/v1/ask-pcific/item-source/test \
-H "Authorization: Bearer $PCIFIC_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"id":"coat-8841","buyer":{"accountId":"opaque-buyer-1"}}'{
"id": "coat-8841",
"item": {
"title": "Wool coat, navy, size M",
"condition": "Used, good",
"delivery": "Tracked, 2 to 4 working days",
"reservation": "cannot confirm who it is reserved for"
}
}Every error is JSON with error (what went wrong), code (a fixed name to branch on), tryThis (the next step) and sometimes problems (the exact fields at fault, as paths). 4xx means fix the request. 5xx means a problem on PCIFIC's side, so wait and try again.
Most errors also have a docs link to their own section on Ask PCIFIC errors, with the usual causes, how to fix it and a request that works. That page starts with the mistakes integrations make most often.
| Code | HTTP | Why it happens | How to fix |
|---|---|---|---|
ASK_QUESTION_MISSING | 400 | The question is missing or only spaces. | Send the customer's question as text, like {"question": "Can I return this?"}. |
ASK_QUESTION_INVALID | 400 | The question must be text. | Send the customer's question as text, like {"question": "Can I return this?"}. |
ASK_QUESTION_TOO_LONG | 400 | The question is over 1,500 characters. | Shorten the question and send it again. |
ASK_ACCOUNT_ID_INVALID | 400 | buyer has an unknown key, an account id has the wrong shape, or a lookup reservation holder is invalid; the error names the field and whether it is in the lookup response. | Inside buyer send only accountId. Use opaque ids of 1 to 128 ASCII letters, digits, dots, colons, underscores or hyphens, never names or usernames. If the error names the item lookup response, correct reservedForAccountId there and test the lookup again. |
ASK_PRICE_INVALID | 400 | A caller price or structured lookup price is malformed; the error names the price field and whether it is in the lookup response. | For caller input, send item.price as {amount: 9575, currency: GBP}, using a nonnegative whole number in the smallest unit and a three letter currency code in capitals. For a lookup response, correct price in the configured lookup and test it again; caller item fields are ignored. |
ASK_QUOTES_INVALID | 400 | quotes was sent but is not true or false. | Send quotes: true to request a document quote, or leave quotes out. |
MODEL_TIER_INVALID | 400 | modelTier is not standard or ultra-fast. | Send modelTier: standard (the default) or ultra-fast, or leave it out. |
INVALID_ITEM | 400 | Something in item has the wrong shape or is too long: item is not an object, item.id is not 1 to 128 characters of text or a number, type, title or url is too long, details has over 60 entries, or a detail is not one plain value. | Read the message, which names the field. Send item as {"id": "abc-123", "title": "...", "details": {...}} with short plain values, or leave item out. |
ASK_ITEM_ID_NOT_ALLOWED | 400 | The item id is . or .., which in a web address means a different folder, not an item. | Send the item's real id, like "abc-123". |
ASK_TURNED_OFF | 403 | Ask PCIFIC is switched off for this account. | Switch it on in the dashboard, or send {"enabled": true} to PUT /api/v1/ask-pcific/settings. |
ASK_CHATS_OFF | 400 | conversationId was sent, but the account keeps no chats (keepChats is false), so there is no chat to carry on. | Leave conversationId out: each question is answered on its own. To keep chats, send {"keepChats": true} to PUT /api/v1/ask-pcific/settings. |
ASK_CONVERSATION_NOT_FOUND | 404 | conversationId is not a chat of this account. It may be wrong, belong to another business, or be older than 30 days after its last question. | Leave conversationId out to start a new chat. |
ASK_ITEM_NOT_FOUND | 404 | Item lookup is set up, and your lookup address answered "not found" for this item id. | Check the item id is right, or turn item lookup off and send the item's details in item.details instead. |
ASK_NO_DOCUMENTS | 409 | The account has no live document to answer from. Either none was added, the only versions are waiting for approval, or the approved documents are unpublished. | Add a document with POST /api/v1/documents or on the dashboard Documents page. If you approve changes first, ask an owner or admin to approve the waiting version there. For an unpublished approved document, use Publish again on Documents. |
ASK_CHAT_TOO_FAST | 429 | This chat has asked 20 questions in the last minute, more than a person can type. | Wait a minute and send the question again. If a real customer sees this, check your code sends each question once, not again on every retry or page refresh. |
ASK_ITEM_LOOKUP_FAILED | 502 | Item lookup is set up, but your lookup address failed, took over 5 seconds, sent back over 256 KB, redirected to a different website, or did not answer a JSON object. | Test the address with POST /api/v1/ask-pcific/item-source/test and check it answers one item as a JSON object. |
ASK_ITEM_LOOKUP_NOT_CONFIGURED | 400 | item.id was sent but listing lookup is not set up for this business. The request is refused before any AI call or usage. | Set up listing lookup in Ask PCIFIC settings, or leave item.id out and send the listing details in the request instead. |
ASK_MODEL_FAILED | 502 | PCIFIC's AI could not finish the answer. This is a problem on PCIFIC's side. | Send the question again in a few minutes. If it still fails, contact PCIFIC support. |
AI_PROVIDERS_BLOCKED | 503 | Every AI model that could answer is from a provider PCIFIC has blocked for your business. | Contact PCIFIC support to allow another AI provider for your business, then send the question again. |
ASK_EMPTY_ANSWER | 502 | The AI finished without writing anything. | Send the question again. If it keeps happening, contact PCIFIC support. |
ASK_TIMEOUT | 504 | The answer took longer than 30 seconds and was stopped. | Send the question again. |
| Code | HTTP | Why it happens | How to fix |
|---|---|---|---|
ASK_ACCOUNT_ID_INVALID | 400 | buyer has an unknown key, an account id has the wrong shape, or a lookup reservation holder is invalid; the error names the field and whether it is in the lookup response. | Inside buyer send only accountId. Use opaque ids of 1 to 128 ASCII letters, digits, dots, colons, underscores or hyphens, never names or usernames. If the error names the item lookup response, correct reservedForAccountId there and test the lookup again. |
ASK_PRICE_INVALID | 400 | A caller price or structured lookup price is malformed; the error names the price field and whether it is in the lookup response. | For caller input, send item.price as {amount: 9575, currency: GBP}, using a nonnegative whole number in the smallest unit and a three letter currency code in capitals. For a lookup response, correct price in the configured lookup and test it again; caller item fields are ignored. |
INVALID_ITEM_SOURCE | 400 | On PUT: url is missing, has no {id}, is over 2,000 characters, is not a public https address, or headerName and headerValue were not sent together. On test: id is missing. | Put {id} where the item's id goes, like https://api.example.com/items/{id}. Send headerName and headerValue together, or neither. |
ASK_ITEM_ID_NOT_ALLOWED | 400 | On test: the item id is . or .., which in a web address means a different folder, not an item. | Send the item's real id, like "abc-123". |
ASK_ITEM_NOT_FOUND | 404 | On test: your lookup address answered "not found" for this id. | Check the item id is right, or send the item's details in item.details instead. |
ASK_NO_ITEM_SOURCE | 409 | On test: item lookup is not set up. | Set it with PUT /api/v1/ask-pcific/item-source. |
ASK_ITEM_LOOKUP_FAILED | 502 | On test: your lookup address failed, took over 5 seconds, sent back over 256 KB, redirected to a different website, or did not answer a JSON object. | Check the address answers one item as a JSON object, then test it again. |
| Code | HTTP | Why it happens | How to fix |
|---|---|---|---|
DOCUMENT_REFRESH_TOO_SOON | 429 | Refresh now was requested for this website document within the last minute. | Wait one minute after the last refresh attempt, then try Refresh now again. |
INVALID_JSON | 400 | The body is not a JSON object. | Send a JSON object with the header "Content-Type: application/json". |
INVALID_FIELD | 400 | A field has the wrong type or is too long. problems names each one. | Fix each place named in problems, using its tryThis, then send the request again. |
INVALID_DOCUMENT_TAGS | 400 | The document tags field is not an array of up to 5 different lowercase words, each 1 to 24 letters (a to z). | Send tags as an array such as ["returns", "shipping"], or [] to clear them. For uploads, send the same JSON array in a part named tags. |
DOCUMENT_TITLE_MISSING | 400 | You sent pasted text with no title. | Add a "title" naming the document, for example "Returns policy". |
DOCUMENT_CONTENT_MISSING | 400 | You sent neither text nor url, or both. | Send the document's text as "text", or its web address as "url", or upload a file as multipart/form-data with a "file" field. |
DOCUMENT_FILE_MISSING | 400 | The upload has no part named file. | Send the document in a multipart/form-data field named "file". |
INVALID_UPLOAD | 400 | The file upload could not be read. | Send the file as multipart/form-data with the file in a field named "file". |
DOCUMENT_TITLE_TOO_LONG | 400 | The title is over 200 characters. | Use a short name for the document, for example "Returns policy". |
DOCUMENT_ADDRESS_NOT_ALLOWED | 400 | The web address is not https, has a user name or password in it, or points at a private or local address. | Use the public https:// address of the page, as it appears in a browser. |
DOCUMENT_EMPTY | 400 | No text was found in the document, for example a scanned PDF, which is only a picture of text. | Check you sent the right file or text. For a scanned PDF, copy its text in and send it as "text" instead. |
DOCUMENT_NOT_HTML | 400 | An uploaded web page (.html or .htm) file has no HTML tags in it, so it is not really a web page. | Upload the real web page, saved from your browser, or save the text as a .txt file and upload that instead. |
DOCUMENT_LIMIT_REACHED | 409 | The business already has 50 documents. | Delete a document you no longer need, or join related documents into one. |
DOCUMENT_NOT_A_WEB_PAGE | 409 | You asked to refresh a document that is pasted text or a file. | To change this document, send its new text or file to PUT /api/v1/documents/{id}/content. |
DOCUMENT_UPLOAD_LIMIT | 429 | Your business has two document uploads or refreshes in progress, or its reserved input bytes are full. All shops and keys share this allowance. Busy background refreshes stay due for the next run. | Try this document upload again in 20 seconds. Retry-After is 20. |
DOCUMENT_UPLOAD_BUSY | 503 | PCIFIC's document upload capacity is full, or no PDF reader became available within two seconds. | Try this document upload again in 20 seconds. Retry-After is 20. |
DOCUMENT_UPLOAD_TIMEOUT | 408 | The document upload did not finish arriving within 20 seconds. | Check your connection, then try the document upload again. Split a large file into smaller documents if needed. |
DOCUMENT_FILE_TOO_LARGE | 413 | The file is larger than 10 MB. | Split the document into smaller files, or paste its text instead. |
DOCUMENT_TOO_LARGE | 413 | The document is over 300,000 characters once converted, or a Word file's text unpacks to over 20 MB. | Split it into smaller documents, for example one per policy. |
DOCUMENTS_FULL | 413 | The documents together would be over 2,000,000 characters. | Delete documents Ask PCIFIC no longer needs, or shorten this one. |
DOCUMENT_TYPE_NOT_SUPPORTED | 415 | The file is not a PDF, Word (.docx), web page (.html), Markdown (.md) or plain text (.txt) file. | Send a PDF, Word (.docx), web page (.html), Markdown (.md) or plain text (.txt) file. |
DOCUMENT_UNREADABLE | 422 | The file is damaged, password protected, text that is not UTF-8 or contains binary control characters, or a PDF that took too long or too much memory to read. | Open the file to check it is not damaged or password protected, or copy its text in and send it as "text" instead. |
DOCUMENT_FETCH_FAILED | 502 | The page could not be read: it does not exist, would not let PCIFIC in, was too slow, is not a web page, PDF or text file, or has almost no text. | Check the address opens in a private browser window without signing in. If the page needs scripts to show its text, upload it as a file or paste its text instead. |
DECISION_MISSING | 400 | The decision is missing or is not "approve" or "reject". Only reachable from the dashboard. | The dashboard sends the decision for you. Pick Approve or Reject on the Documents page. |
VERSION_NOT_WAITING | 409 | The version is not waiting for approval, or another person decided it a moment before. Only reachable from the dashboard. | Only a version with status waiting can be decided. Open the document to see its waiting version, if it has one. |
DOCUMENT_DECISION_NEEDS_DASHBOARD | 403 | An API key tried to approve or reject a waiting version. No API key, test or live, is allowed to. | Ask an owner or admin of your business to approve or reject it on the Documents page of your PCIFIC dashboard. |
NOT_FOUND | 404 | No document or version with this id for your business. | Check the id. Ids from another business, or from before it was deleted, are not found. |
| Code | HTTP | Why it happens | How to fix |
|---|---|---|---|
DOCUMENT_UNDO_UNAVAILABLE | 409 | The document's 10-second Undo window ended, or it is not awaiting removal. | Reload Documents to check the list. If removed, add it again from your original text, file or web address. |
| Code | HTTP | Why it happens | How to fix |
|---|---|---|---|
INVALID_LIMIT | 400 | limit in the address is not a whole number from 1 to 200. | Send a number from 1 to 200, like ?limit=50, or leave it out for the newest 50. |
The unanswered list accepts limit from 1 to 200, default 50. Other values return 400 INVALID_LIMIT. Send a whole number in that range or leave limit out.
| What | Limit | What happens past it |
|---|---|---|
| A question | 1 to 1,500 characters, and the whole body 16 KB | ASK_QUESTION_TOO_LONG, or BODY_TOO_LARGE for the body |
| item.id | 1 to 128 characters | INVALID_ITEM |
| item.type, item.title, item.url | 40, 300 and 2,000 characters | INVALID_ITEM |
| item.details | 60 entries, each a plain value of up to 2,000 characters | INVALID_ITEM |
| Time for one answer | 30 seconds, up to 4 rounds of tool use and 2 web searches | ASK_TIMEOUT |
| Time the website waits for PCIFIC | 40 seconds for questions and for adding, replacing or refreshing a document, 15 for other calls | BACKEND_UNAVAILABLE |
| A chat | The last 8 turns are used. Kept 30 days after its last question | A chat id after that is ASK_CONVERSATION_NOT_FOUND |
| Questions in one chat | 20 a minute | ASK_CHAT_TOO_FAST |
| Unanswered questions | Kept 30 days. limit 1 to 200, default 50 | Older ones are deleted |
| Documents | 50 per business | DOCUMENT_LIMIT_REACHED |
| One document | 300,000 characters once converted | DOCUMENT_TOO_LARGE |
| All documents together | 2,000,000 characters | DOCUMENTS_FULL |
| A file | 10 MB | DOCUMENT_FILE_TOO_LARGE |
| A Word file's text once unpacked | 20 MB | DOCUMENT_TOO_LARGE |
| A title | 200 characters | DOCUMENT_TITLE_TOO_LONG |
| Versions kept per document | The live one, a waiting one and the newest 5 | Older versions are removed |
| fallbackMessage, supportLink | 500 and 2,000 characters | INVALID_SETTING |
| Item lookup | 5 seconds and 256 KB per item | ASK_ITEM_LOOKUP_FAILED |
| Web search | 2 searches per answer, top 3 pages, each cut to 8,000 characters | The AI answers with what it has |
The limits that apply to every address, such as requests a minute, are on the Errors, limits and retries page.