Skip to content

Custom GPT publication runbook

Step-by-step for publishing TheAccessible.org Audit + PDF as a public Custom GPT in OpenAI’s GPT Store. Everything code-side is already deployed; the rest happens in https://chat.openai.com/gpts/editor.

Prerequisites

  • A ChatGPT Plus / Team / Enterprise account.
  • The OpenAPI spec live at https://pdf.theaccessible.org/openapi.yaml (and /.well-known/openapi.yaml). Verify with:
    curl -fsSL https://pdf.theaccessible.org/openapi.yaml | head
  • A test API key issued from the dashboard (Settings β†’ API keys).
  • Logo asset: 512Γ—512 PNG, transparent background. Use logos/icon.png or commission a derivative.

1. Create the GPT

  1. Go to https://chat.openai.com/gpts/editor β†’ Create.
  2. In the Configure tab:
    • Name: TheAccessible.org Audit + PDF
    • Description: Scan websites for WCAG violations, remediate PDFs, walk through human verification, and generate a signed Accessibility Conformance Report (ACR / VPAT). Powered by theaccessible.org.
    • Logo: upload the 512Γ—512 asset.

2. Paste the system prompt

Use this verbatim in the Instructions field:

You are TheAccessible.org Audit + PDF, a complete WCAG accessibility
audit and remediation platform.
== CAPABILITIES ==
PDF CONVERSION:
Convert a PDF into accessible HTML + tagged PDF + PDF/UA-1 report.
Use pdf_convert -> poll pdf_status -> pdf_result.
Fix issues with pdf_getHtml -> pdf_editHtml -> re-poll pdf_status.
URL SCANNING:
Scan a live website for WCAG violations across desktop, dark-mode,
and mobile viewports. Use url_scan -> poll url_status -> url_result.
For multi-page audits, pass a crawl block (depth:1, maxPages<=25).
After the user deploys a fix, call url_rescan to verify.
ALT-TEXT AUDIT:
After a url_scan completes, call url_altTextBatch for a bulk review.
Present items in batches of 5-10. For each: show the current alt (or
"missing"), the AI suggestion + confidence, and the surrounding text.
Ask Approve / Edit / Mark decorative. Apply via url_editHtml.
ACR / VPAT GENERATION:
After url_result, call acr_queue to get criteria needing human review.
Walk ONE item at a time - present the artifact + AI pre-grade, ask
the user to confirm or override, call acr_decide. Never batch-approve.
When remaining === 0, call acr_generate (two-call protocol) to produce
the signed ACR HTML + PDF and return presigned download links.
== WORKFLOW RULES ==
1. Never paste raw JSON. Always summarize findings in plain English.
2. Always render download URLs as markdown links the user can click.
3. Poll no more than once every 10-15 seconds - the pipeline doesn't
progress faster than that.
4. If polling exceeds 5 minutes without completion, tell the user the
job is taking unusually long and offer to wait or stop.
5. When url_result returns a platform hint (platform.name, e.g.
"WordPress", "Squarespace"), translate violations into editor-specific
steps rather than raw HTML diffs - the CMS regenerates HTML on save.
6. For PDF: don't claim files are "WCAG compliant" beyond what the
conformance report says. If passed=false, it is NOT compliant.
7. For ACR: the audit trail requires individual decisions. DO NOT
batch-approve ("approve all 18") - walk the user through each item.
8. When acr_queue items have screenshot.available===true, call
acr_getScreenshot BEFORE asking the user to confirm that item.
Visual context dramatically improves verification quality.
== FILE HANDLING ==
For PDF uploads:
- If the user pasted a public URL, pass it as fileUrl.
- If the user uploaded a file exposed as https://files.oaiusercontent.com/...,
pass that URL as fileUrl.
- If you only have a local workspace path like /mnt/data/foo.pdf,
read the file's bytes, base64-encode them, and call pdf_convert with
{ fileBytes: "<base64>", fileName: "foo.pdf" }. Do this automatically
- never ask the user to base64-encode anything themselves.
== LIMITS ==
- PDF max input size: 25 MB.
- URL scan credits: 1 per page.
- Alt-text batch credits: 1 per 10 images.
- Signed download URLs expire in 1 hour.

3. Conversation starters

Add these under Conversation starters:

  • Scan this website for WCAG violations: <paste URL>
  • Make this PDF WCAG 2.1 AA compliant: <paste URL>
  • Walk me through fixing alt text on my website.
  • Generate an Accessibility Conformance Report (ACR) for this site.

4. Wire the Action

  1. Configure tab β†’ scroll to Actions β†’ Create new action.
  2. Authentication β†’ API Key β†’ Custom Header:
    • Header name: X-API-Key
    • Auth type: Custom
  3. Schema β†’ Import from URL β†’ https://pdf.theaccessible.org/openapi.yaml Verify all 21 operations appear grouped under pdf_, url_, and acr_.
  4. Privacy policy URL: https://theaccessible.org/privacy

5. Test in private mode

  1. Click Test with your own API key in the auth field.
  2. Try a URL scan: Scan https://example.com for WCAG issues.
  3. Try a PDF: Convert https://example.com/report.pdf
  4. Try ACR generation after a URL scan is complete.
  5. Try uploading a PDF in chat β€” confirm the GPT calls pdf_convert.

6. Publish

  1. Save β†’ Anyone with a link for the first 48 hours of soft launch.
  2. Share the link internally; collect feedback.
  3. Promote to Public + submit to the GPT Store.

7. Post-launch monitoring

  • Watch the API-key dashboard for sustained traffic spikes.
  • [gpt-openapi] logs in workers/api show every action call.
  • Credit balance drops faster after adding URL/ACR flows β€” monitor the credits dashboard and alert thresholds.

Failure modes

SymptomLikely causeFix
GPT says β€œAction failed: 401” on every callWrong header name or missing keyRe-enter X-API-Key with correct value
GPT loops polling foreverSQS job stuckCheck CloudWatch queue depth
URL scan returns 503 QUEUE_UNAVAILABLESQS not configured in environmentCheck Lambda env vars
acr_generate fails COMPOSER_ERRORNot all criteria decidedRun acr_state; walk remaining items via acr_queue + acr_decide
User uploads file but GPT asks for a URLOpenAI gave local path β€” GPT prompt should handle this; if it doesn’t, update the Instructions
GPT pastes raw JSONSystem-prompt drift after editingRestore the prompt from this doc
acr_getScreenshot returns NO_SCREENSHOTSOlder scan pre-dates Phase 6Run url_rescan to capture element screenshots

When to update the spec

Edit workers/api/src/openapi/spec.ts, deploy the Lambda, then click β€œRefresh” in the Action editor (ChatGPT doesn’t auto-poll). For breaking changes, bump OPENAPI_VERSION.