Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Generate production-ready AdvPL/TLPP code that consumes external REST APIs using the framework FWRest class. FWRest is the HTTP client class — it is the counterpart to the @Get/@Post annotation-based REST server (see tlpp-rest-endpoint-generator for exposing endpoints, not consuming them).
FWRest wraps low-level HTTP socket calls and supports the four standard verbs GET, POST, PUT, DELETE (no native PATCH support). It handles SSL automatically through appserver.ini socket configuration.
When to Use
Use this skill when generating code that:
Calls a third-party REST API from inside Protheus (integrations with CRMs, payment gateways, ERPs, government services, etc.)
Sends JSON payloads to external services
Pulls data from external endpoints into a Protheus routine
Needs HTTP Basic, Bearer/JWT, or OAuth 2.0 authentication
Replaces legacy HTTPCGet / HTTPCPost / HTTPQuote calls with the framework client
Build headers — Plain Array of "Key: Value" strings, e.g. {"Content-Type: application/json", "Authorization: Bearer xyz"}.
Invoke verb — :Get(aHead), :Post(aHead), :Put(aHead, cBody), :Delete(aHead, cBody). All return .T. on success.
Read result — GetResult() on success (response body as character), GetLastError() on failure, GetHTTPCode() for the numeric status.
Path vs Query Parameters
Concern
API
Example
Path segments
SetPath("/api/v1/customers/123")
URL: /api/v1/customers/123
Query string (inline)
SetPath("/api/v1/customers?page=1")
URL: /api/v1/customers?page=1
Query string (separate)
SetGetParams("page=1&size=20")
Appended after path
GET param via verb
:Get(aHead, "page=1")
Appended after path
Special characters in query values must be URI-encoded via the Escape() function — otherwise the request will fail or be misinterpreted.
Status Code Semantics
Method
Behavior
Get()
Returns .T. only for HTTP 200 (legacy) or 200–299 (with SetLegacySuccess(.F.))
Post()
Returns .T. for 200 or 201 (legacy) or 200–299 (with SetLegacySuccess(.F.))
Put() / Delete()
Returns .T. for 200 or 201 (legacy) or 200–299 (with SetLegacySuccess(.F.))
SetChkStatus(.F.)
Disables internal HTTP code validation — verb returns .T. if the connection succeeded, regardless of HTTP code. You then call GetHTTPCode() to decide. Use this for APIs that return 204, 207, 3xx, or 4xx as part of the contract.
No PATCH Support
FWRest does not support the PATCH verb. If the target API requires PATCH, generate code using HTTPQuote() instead and note this limitation explicitly.
Bundled Reference Files
This skill uses progressive disclosure. The SKILL.md body covers the architecture, decision logic, and the generation checklist. Detailed method reference, code templates, and authentication patterns are in the references/ directory — read them on demand based on the scenario:
Looking up exact method signatures, parameter types, minimum LIB version per method, or behavior of SetChkStatus/SetLegacySuccess/SetTimeOut/GetHTTPCode
Complete FWRest method reference table with syntax, parameters, returns, LIB version requirements
Standard CRUD (200/201 only matter): leave defaults.
API uses full 2xx range (e.g. 202 Accepted, 204 No Content): call oClient:SetLegacySuccess(.F.) (requires LIB 20240812+).
Need to read body of 4xx/5xx responses: call oClient:SetChkStatus(.F.) and inspect GetHTTPCode() + GetResult() manually.
Step 4: Wrap in Try/Catch + Logging
Wrap every FWRest invocation in a TLPP Try/Catch block. Log failures via FWLogMsg() including the URL, HTTP code, and the truncated response body. Never log secrets (tokens, passwords).
Step 5: Validate Against Checklist
Use the checklist below to verify the generated code covers all requirements.
FWRest Client Generation Checklist
Structure
#include "totvs.ch" (AdvPL) or #include "tlpp-core.th" (TLPP) present, in lowercase
User Function declares oClient, aHeader, cBody, cResponse, nHttpCode as locals with explicit types (TLPP as Object, as Array, etc.)
FWRest():New(cHost) receives ONLY the base URL — path is set via SetPath()
Request Construction
SetPath() called with leading /
Query parameter values passed through Escape() when they may contain spaces or special chars
Headers built as an Array of "Key: Value" strings (note the literal space after the colon)
Content-Type header included for POST/PUT bodies (application/json, application/xml, etc.)
Body serialized via oJson:toJson() — never built by string concatenation when the data is dynamic
SetPostParams(cBody) called before:Post() (Post body is NOT a parameter of :Post())
PUT/DELETE bodies passed as the second positional argument of :Put(aHead, cBody) / :Delete(aHead, cBody)
Authentication
Secrets read from GetMV() parameter or environment, never hardcoded