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.pngor commission a derivative.
1. Create the GPT
- Go to https://chat.openai.com/gpts/editor β Create.
- 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.
- Name:
2. Paste the system prompt
Use this verbatim in the Instructions field:
You are TheAccessible.org Audit + PDF, a complete WCAG accessibilityaudit 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
- Configure tab β scroll to Actions β Create new action.
- Authentication β API Key β Custom Header:
- Header name:
X-API-Key - Auth type:
Custom
- Header name:
- Schema β Import from URL β
https://pdf.theaccessible.org/openapi.yamlVerify all 21 operations appear grouped under pdf_, url_, and acr_. - Privacy policy URL:
https://theaccessible.org/privacy
5. Test in private mode
- Click Test with your own API key in the auth field.
- Try a URL scan:
Scan https://example.com for WCAG issues. - Try a PDF:
Convert https://example.com/report.pdf - Try ACR generation after a URL scan is complete.
- Try uploading a PDF in chat β confirm the GPT calls pdf_convert.
6. Publish
- Save β Anyone with a link for the first 48 hours of soft launch.
- Share the link internally; collect feedback.
- 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
| Symptom | Likely cause | Fix |
|---|---|---|
| GPT says βAction failed: 401β on every call | Wrong header name or missing key | Re-enter X-API-Key with correct value |
| GPT loops polling forever | SQS job stuck | Check CloudWatch queue depth |
| URL scan returns 503 QUEUE_UNAVAILABLE | SQS not configured in environment | Check Lambda env vars |
| acr_generate fails COMPOSER_ERROR | Not all criteria decided | Run acr_state; walk remaining items via acr_queue + acr_decide |
| User uploads file but GPT asks for a URL | OpenAI gave local path β GPT prompt should handle this; if it doesnβt, update the Instructions | |
| GPT pastes raw JSON | System-prompt drift after editing | Restore the prompt from this doc |
| acr_getScreenshot returns NO_SCREENSHOTS | Older scan pre-dates Phase 6 | Run 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.