Fwrest client generator
Skill tbc-servicos/dataagile-agent-kit/protheus/skills/fwrest-client-generator
Plugin Claude Code para Protheus e ADVPL/TLPP — base 155k+ registros, Agent Teams, compilação TDS-CLI, testes TIR e MCP PO-UI
npx -y skills add tbc-servicos/dataagile-agent-kit --skill fwrest-client-generatorAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 3 stars3 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Generate AdvPL/TLPP code that CONSUMES external REST APIs using the FWRest client class. Covers GET, POST, PUT, DELETE verbs, header construction, query/path parameters, JSON body serialization, authentication (No Auth, HTTP Basic, Bearer Token/JWT, OAuth 2.0), timeout, SSL, status code handling, error treatment, and TLPP try/catch patterns. Use when user says 'consume REST API', 'call external API', 'FWRest', 'oRestClient', 'integrate with third-party API', 'HTTP client AdvPL', 'POST JSON Protheus', 'Bearer token AdvPL'.
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
11.6 KB, as published. Nobody here has run it
FWRest Client Generator
Overview
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/HTTPQuotecalls with the framework client
Do NOT use this skill for:
- Exposing endpoints from Protheus → use
../tlpp-rest-endpoint-generator/SKILL.md - Workstation-side HTTP calls that must run on the user's machine → use
HTTPCGet/HTTPCPostwith WebAgent - File downloads from non-REST endpoints → use
HTTPQuoteorWSDownload
FWRest Architecture
Lifecycle
A typical FWRest call follows this five-step lifecycle:
- Instantiate —
oClient := FWRest():New(cHost)wherecHostis the base URL only (scheme + host + optional port), e.g."https://api.example.com". - Configure —
SetPath(),SetPostParams(),SetGetParams(),SetTimeOut(),SetChkStatus(),SetLegacySuccess(). - Build headers — Plain
Arrayof"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:
| Reference File | When to Read | Content |
|---|---|---|
| references/fwrest-api-reference.md | 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 |
| references/fwrest-client-templates.md | Generating any FWRest call — GET, POST, PUT, DELETE, JSON parsing, error handling, file upload (.gz), header construction | Full code templates for all 4 HTTP verbs, JSON body construction, response parsing, generic error-handling wrapper |
| references/fwrest-authentication-patterns.md | Implementing HTTP Basic, Bearer Token / JWT, API Key, or OAuth 2.0 (client credentials / authorization code) authentication | Header templates for each auth scheme, token-refresh pattern, secret storage guidance |
Also refer to references/sonarqube-rules-reference.md for the complete SonarQube rules reference shared across skills.
Generation Workflow
Step 1: Gather Requirements
Identify from the user's request:
- Target API — base URL, path, and HTTP verb(s)
- Authentication scheme — None, Basic, Bearer/JWT, API Key, or OAuth 2.0
- Payload format — JSON (default), XML, form-encoded, binary/gzip
- Expected response codes — only 2xx, or also 204/3xx/4xx as part of contract
- Timeout requirement — default 120s vs custom (e.g. webhook endpoints with 5s SLA)
- Whether the call is part of a transaction — affects error handling strategy
Step 2: Load Templates
Read references/fwrest-client-templates.md for the verb-specific template. Combine with the auth header pattern from references/fwrest-authentication-patterns.md.
Step 3: Pick the Status-Code Strategy
- 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 inspectGetHTTPCode()+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,nHttpCodeas locals with explicit types (TLPPas Object,as Array, etc.) -
FWRest():New(cHost)receives ONLY the base URL — path is set viaSetPath()
Request Construction
-
SetPath()called with leading/ - Query parameter values passed through
Escape()when they may contain spaces or special chars - Headers built as an
Arrayof"Key: Value"strings (note the literal space after the colon) -
Content-Typeheader 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 - HTTP Basic:
"Authorization: Basic " + Encode64(cUser + ":" + cPass) - Bearer/JWT:
"Authorization: Bearer " + cToken - OAuth 2.0 token-acquisition call is a separate FWRest call to the auth server, cached for the token's
expires_inwindow - Token never logged or echoed in error responses
Response Handling
- Verb result captured in a local
lOk(e.g.lOk := oClient:Post(aHeader)) -
GetHTTPCode()retrieved into a local before any branching -
GetResult()parsed viaJsonObject():New() + :fromJson()and thefromJson()return checked (returnsNilon success, error string otherwise) - Failure branch reads
GetLastError()ANDGetHTTPCode()(both can be informative)
Robustness
-
SetTimeOut()set explicitly (default 120s is often too long for synchronous calls) - Calls wrapped in
Try/Catchto capture transport-layer exceptions -
SetChkStatus(.F.)used when the API returns 204/4xx as part of contract -
SetLegacySuccess(.F.)used when the API uses the full 2xx range -
FreeObj(oClient)after use in long-running routines to release the socket promptly
Logging & Observability
- Successful calls logged at
INFOlevel with URL + HTTP code (no body) - Failed calls logged at
ERRORlevel with URL + HTTP code + truncated response (max ~500 chars) -
FWLogMsg("ERROR", , "REST_CLIENT", FunName(), , "01", cMessage, 0, 0, {})pattern used - No use of
ConOut()for production logging (only acceptable in standalone smoke tests) - No secrets, tokens, passwords, or full request bodies emitted to logs
SonarQube Compliance
- No hardcoded passwords, tokens, or API keys in source code
- No
IIF()— useIf/Else/EndIfblocks -
GetMV()calls outside of loops - No UI functions (
MsgAlert,MsgYesNo,Aviso,Help) inside the call path of a transaction or scheduled job - Includes in lowercase (e.g.,
#include "totvs.ch") - No use of
RpcSetEnvinside REST endpoint handlers that themselves invoke FWRest — environment must already be prepared
Refer to references/sonarqube-rules-reference.md for the complete SonarQube rules reference.
Common Pitfalls
| Pitfall | Symptom | Fix |
|---|---|---|
Full URL passed to New() | 404 or empty result | Pass only https://host:port; use SetPath() for the path |
Body passed to :Post() as argument | Body ignored, empty POST sent | Use SetPostParams(cBody) before :Post(aHead) |
| 204 response hangs ~2 minutes | Slow integrations | Set SetTimeOut(nSec) to a small value, or use HTTPQuote() as alternative |
| Header missing space after colon | Server rejects request | Always write "Key: Value" with a space |
| Query string not escaped | Garbled parameters | Wrap values with Escape() |
| 4xx body unreadable | GetResult() returns empty | Call SetChkStatus(.F.) first; then read GetResult() even on failure |
| Hardcoded credentials | SonarQube blocker | Read from GetMV("MV_XYZTOK",,"") parameter |
| PATCH attempted | Compile error / no such method | FWRest does not support PATCH — use HTTPQuote() |
Gives 0 of the 12 instructions most auth identity skills give
Counted across 409 of the 410 authors here whose files we hold, read 2026-08-06
- hash passwords with bcrypt or argon2in 53 of 409, across 43 files
- use parameterized queriesin 47 of 409, across 39 files
- load SECRET_KEY from environment variablesin 23 of 409, across 14 files
- validate all input server-sidein 19 of 409, across 11 files
- refresh access tokens before expiryin 17 of 409, across 9 files
- store tokens in httponly cookiesin 17 of 409, across 16 files
- store refresh tokens securelyin 16 of 409, across 6 files
- validate webhook signatures before processingin 15 of 409, across 5 files
- sanitize user inputsin 15 of 409, across 9 files
- implement rate limiting on auth endpointsin 14 of 409, across 9 files
- encrypt sensitive data at restin 13 of 409, across 10 files
- validate uploaded file extensions and sizesin 12 of 409, across 5 files
Said here and by no other author read
- Pass only the base URL to FWRest():New().
- Set the request path via SetPath().
- URI-encode query parameter values using Escape().
- Build headers as an array of space-separated strings.
- Set the POST body via SetPostParams before calling Post.
- Pass PUT or DELETE bodies as the second positional argument.
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once.