Connect a ChatGPT Custom GPT
Wire the Caramel API into a ChatGPT Custom GPT via OpenAI Actions. Once set up, users can list forms, submit leads, check domain verification, and review usage in plain conversation — ChatGPT handles parameter extraction and Caramel handles the operations.
Estimated time: 15 minutes. You need a ChatGPT Plus account.
Why REST, not MCP
Section titled “Why REST, not MCP”ChatGPT Actions speak OpenAPI 3.0, not JSON-RPC 2.0. Your Custom GPT calls the Caramel REST gateway at gateway.caramelme.com rather than the MCP endpoint. The underlying data and auth are the same — only the call shape differs.
Step 1 — Get an OAuth client
Section titled “Step 1 — Get an OAuth client”ChatGPT’s redirect URI follows this pattern:
https://chat.openai.com/aip/g-<your_gpt_id>/oauth/callbackYou won’t know <your_gpt_id> until the GPT is created, so request a wildcard client upfront.
Email aymen@reactmotion.com:
- App name
- Redirect URI:
https://chat.openai.com/aip/*/oauth/callback - Requested scopes:
meta:read forms:read forms:write
You receive a client_id. There is no client secret — PKCE is mandatory.
Step 2 — Create the Custom GPT
Section titled “Step 2 — Create the Custom GPT”In ChatGPT:
- Click your profile → My GPTs → Create a GPT.
- Open the Configure tab.
- Set Name:
Caramel Assistant - Set Description:
Manages Caramel marketing forms, contacts, and audiences. - Paste the following into Instructions:
You are Caramel Assistant. You help users manage their Caramel marketingcommunications, forms, and customer audiences.
Available actions (auto-discovered from the OpenAPI spec):- caramelV1BusinessList — list the user's businesses- caramelV1FormList — list forms for a business- caramelV1FormSubmit — submit data to a form- caramelV1DomainStatus — check sender-domain verification- caramelV1TemplateList — list deployed templates- caramelV1MetaUsage — get this month's usage
Conventions:- Start every session by calling caramelV1BusinessList to learn the user's business IDs.- Refer to businesses by name, not by raw ID.- Never invent business IDs or form IDs — discover them via the list tools first.- When a call returns 429, ask the user to wait a minute and try again.- When a call returns 403 tier_required, explain which tier is needed and suggest caramelme.com/billing.
Privacy:- Never reveal OAuth tokens or internal request IDs.- Never store contact data beyond the duration of the action call.
Tone: concise, friendly, no emoji.- Add optional Conversation starters: “List my forms”, “Check my domain status”, “How much usage do I have left?”
Step 3 — Import the OpenAPI spec
Section titled “Step 3 — Import the OpenAPI spec”- Scroll to Actions → Create new action.
- In the Schema field, paste the contents of
docs/public-api/openapi-3.0.yamlfrom this repository.
Important ChatGPT requires OpenAPI 3.0, not 3.1. The repository ships both:
openapi.yaml(3.1, for tooling) andopenapi-3.0.yaml(3.0, for ChatGPT). Use the 3.0 file. The 3.0 file is auto-generated from 3.1 — do not hand-edit it.
Coming soon A hosted spec URL at
gateway.caramelme.com/v1/openapi.jsonis on the roadmap. Until then, paste-import from the repository file is the path. Alternatively, host the 3.0 file at any public HTTPS URL you control (for example, a GitHub raw URL) and use ChatGPT’s Import from URL field.
After parsing, you should see these operations in the actions list:
caramelV1BusinessListcaramelV1FormListcaramelV1FormSubmitcaramelV1DomainStatuscaramelV1TemplateListcaramelV1MetaUsage
Spec import errors:
| Error | Cause | Fix |
|---|---|---|
| ”Could not parse the schema” | Wrong file version | Use openapi-3.0.yaml, not openapi.yaml |
| ”Server URL is missing” | servers: block removed | Re-fetch the canonical file |
| ”Unsupported security scheme” | Modified copy with flows.implicit | The official spec uses bearerAuth only |
Step 4 — Configure OAuth
Section titled “Step 4 — Configure OAuth”In the same Actions panel, click Authentication:
| Field | Value |
|---|---|
| Type | OAuth |
| Client ID | The client_id from step 1 |
| Client Secret | Leave empty (PKCE only) |
| Authorization URL | https://app.caramelme.com/oauth/authorize |
| Token URL | https://app.caramelme.com/oauth/token |
| Scope | meta:read forms:read forms:write |
| Token Exchange Method | Default (POST request) |
Click Save.
Step 5 — Test
Section titled “Step 5 — Test”In the Preview pane:
List my Caramel businesses.
ChatGPT prompts you to authorize. Click Authorize, complete the magic-link flow. ChatGPT calls caramelV1BusinessList and responds with your business name and tier.
Try:
What forms are configured?
ChatGPT calls caramelV1FormList with the business ID it discovered in the previous step.
Is mail.brewmaster.cafe verified?
ChatGPT calls caramelV1DomainStatus.
Step 6 — Publish (optional)
Section titled “Step 6 — Publish (optional)”Click Save → Publish:
- Only me — private testing.
- Anyone with a link — shareable.
- Everyone — public in the GPT Store. Email
aymen@reactmotion.comto coordinate if you use the “Caramel” name in the GPT title.
When published publicly, each user goes through their own OAuth flow against their own Caramel business. Your client_id is shared across all users; each user gets a distinct token.
What ChatGPT handles well
Section titled “What ChatGPT handles well”- Listing and summarizing — “Show me my forms and their submission counts.”
- Filling defaults — “Submit this lead” (ChatGPT discovers the right form via list, prompts for missing fields).
- Multi-step orchestration — “Check my domain, then list my templates.”
Limitations
Section titled “Limitations”- Bulk operations — ChatGPT calls one action at a time. For 1,000 contacts, write a script. See Sync contacts.
- Scheduled tasks — Custom GPTs have no background task support. “Submit this every Monday” isn’t possible through a GPT.
- File uploads — ChatGPT can’t pass binary data to actions. For forms with file fields, call the REST gateway directly.
Token lifetime
Section titled “Token lifetime”ChatGPT manages OAuth refresh internally. Tokens expire after 1 hour and refresh automatically. If a user doesn’t use the GPT for 30+ days, the refresh token expires and they’re prompted to reauthorize.
Error reference
Section titled “Error reference”| Code | Meaning | GPT response |
|---|---|---|
401 unauthorized | Token expired | ChatGPT re-authorizes automatically in most cases |
403 tier_required | Business tier too low | Explain upgrade path: caramelme.com/billing |
403 scope_required | OAuth scope missing | ”Disconnect and reconnect with the additional scope” |
429 rate_limited | Per-token cap hit | Ask user to wait a minute |
404 form_not_found | Form inactive or ID wrong | ”Make sure the form is active in the Caramel dashboard” |
The instructions block from step 2 already covers these — ChatGPT paraphrases them to the user.
Next steps
Section titled “Next steps”- Build with Lovable — same Caramel backend, MCP instead of REST.
- Sync contacts — bulk operations that Custom GPTs can’t handle.
- Authentication — full OAuth flow details.
- Tool reference — every tool, parameter, and error code.