Pinstripes
Chat

Vision & documents

Two tiers accept image input alongside text:

TierBest for
ps/seeGeneral vision — describe images, answer questions, read screenshots, reason over charts and UIs
ps/docsDocument extraction — turn document images into clean text/structure (OCR-style)

Both use the standard OpenAI multimodal message format. Images go inline in the message — no separate upload endpoint.

Sending an image

Add an image_url part to the content array of a user message, alongside your text prompt. Images can be base64 data-URIs or public URLs.

curl -X POST https://api.pinstripes.io/v1/chat/completions \
  -H "Authorization: Bearer sk-ps-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "ps/see",
    "messages": [{
      "role": "user",
      "content": [
        {"type": "text", "text": "What does this screenshot show?"},
        {"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBORw0KGgo..."}}
      ]
    }]
  }'

Python (base64)

import base64
from openai import OpenAI

client = OpenAI(base_url="https://api.pinstripes.io/v1", api_key="sk-ps-...")

with open("screenshot.png", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()

resp = client.chat.completions.create(
    model="ps/see",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "What does this screenshot show?"},
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{b64}"}},
        ],
    }],
)
print(resp.choices[0].message.content)

Public URL instead of base64

{
  "type": "image_url",
  "image_url": { "url": "https://example.com/chart.png" }
}

Either works. Data-URIs are convenient for local files; public URLs keep request size down (the image must be reachable from the internet).

Multiple images

ps/see accepts more than one image per message — add more image_url parts:

"content": [
    {"type": "text", "text": "What changed between these two screenshots?"},
    {"type": "image_url", "image_url": {"url": before_uri}},
    {"type": "image_url", "image_url": {"url": after_uri}},
]

Document extraction with ps/docs

ps/docs is tuned for reading document images and returning their text and structure. Usage is identical — send the page as an image:

resp = client.chat.completions.create(
    model="ps/docs",
    messages=[{
        "role": "user",
        "content": [
            {"type": "text", "text": "Extract all text from this document."},
            {"type": "image_url", "image_url": {"url": f"data:image/png;base64,{page_b64}"}},
        ],
    }],
)
print(resp.choices[0].message.content)

Working with PDFs

ps/docs takes images, not raw PDF bytes — rasterize each page first:

from pdf2image import convert_from_path   # pip install pdf2image (needs poppler)

pages = convert_from_path("invoice.pdf", dpi=200)
for i, page in enumerate(pages):
    page.save(f"page_{i}.png")
    # send each page_{i}.png to ps/docs as above

Render at 150–300 DPI for reliable text extraction. Process pages individually and stitch results on your side.