Skip to main content
github.com/plainrouter/sdk-go is the official Go SDK generated from Plainrouter’s signed OpenAPI contract. Release v0.6.0 targets signed API contract 0.5.0 and adds canonical package documentation and runnable examples.

Requirements

  • Go 1.23 or newer.
  • A Signals workspace secret.
  • Server-side code. Do not put the secret in browser or distributed client code.

Install

Review the package on Go Packages and the generated source in plainrouter/sdk-go.

Create an authenticated client

Create one client with the Signals workspace secret. plainrouter.New sends it as a bearer token on every request:
Generated request and response models live in the openapi subpackage. client.OpenAPI() returns the complete generated client for operations outside Events, Operations and Sandbox. Code written for v0.5 keeps compiling with the deprecated NewConfiguration, NewAPIClient and ContextAccessToken helpers, but generated type names now need the openapi qualifier. Load the secret from your environment or secret manager rather than writing it in source code. The Go SDK does not accept an MCP workspace execution token or OAuth management credential.

Send a Meta conversion

Send a server-side purchase through Plainrouter to your connected Meta destination. This recipe uses Plainrouter’s SDK and credentials, not the direct Meta Graph API. A successful create response confirms ingestion; inspect destination delivery separately. Before sending, confirm settlement on your server, load the order’s recorded advertising consent, and select the backend as the purchase owner. This request can create a real conversion. Use the sandbox for synthetic validation or a controlled destination test during setup.

Create and send a purchase

The following helper package accepts a paid order from your application. Use a stable, non-personal order ID, a decimal-string total, an actual checkout URL without personal data, and the original purchase and consent times. Parse stored times with their timezone; do not replace them with time.Now() during retries. The published v0.6.0 client wraps consented requests in CreateEventRequestAnyOf. Its event_time wrapper supports an ISO-8601 string; this example uses that branch rather than narrowing a Unix timestamp to int32.
Load PLAINROUTER_SIGNAL_SECRET from your server environment or secret manager and create the client as shown in Create an authenticated client. Call PurchaseEvent(purchase) after loading the paid order; if it succeeds, pass that request to SendPurchase(ctx, client, event). The returned model exposes GetEventId() and GetDuplicate() for both new and duplicate receipts. The helper checks the recorded grant values; it does not obtain consent or establish permission by itself. Do not change an unknown decision to granted. Generated models also do not replace server-side validation. Include only permitted identity values and actual browser identifiers; empty optional values are omitted. Plainrouter normalizes and hashes supported raw identity fields before Meta delivery.

Reuse the client and context safely

Create one client with plainrouter.New and reuse it. Derive a request context with a deadline from your job or HTTP request context, and call its cancellation function after the request. In v0.6.0 the client sends the token as a default Authorization header; never log the client configuration or token. A deadline or lost connection can leave acceptance uncertain. Persist one payload per paid order before sending, including the event ID, original purchase time, amount and applicable consent snapshot. Retry that stored payload after checking that advertising use is still permitted. Do not rebuild it with fresh timestamps or identity data.
  • HTTP 202, duplicate: false: a new event was accepted for processing.
  • HTTP 200, duplicate: true: the event was already accepted. The retry does not update or enrich it.
  • An uncertain timeout requires the same event ID and payload on retry. A new ID can represent another conversion.
Your application owns durable job retries and concurrent-order guards. SDK request idempotency does not make a payment operation idempotent. A separate browser signalq("track", ...) call generates its own ID and cannot accept this recipe’s order ID. Choose one purchase owner, and avoid sending the same checkout through SDK, managed browser tracking and Stripe verified revenue. See event-ID deduplication.

Confirm destination delivery

Call client.Events.GetEvent(ctx, receipt.GetEventId()).Execute() for the receipt returned by SendPurchase. Check the error and HTTP status before reading the event and deliveries; close any returned response body. Use a fresh, non-expired request context for this later check. A delivery marked accepted confirms Meta acceptance. queued, sent and retrying are pending; an empty delivery list is not a success receipt. Follow delivery statuses and Meta troubleshooting for failed or skipped deliveries. Acceptance does not guarantee attribution.

Troubleshoot a purchase request

Configure another API origin

The generated configuration defaults to the Plainrouter Conversion API. Override its server only for a Plainrouter-provided region or a controlled test environment.

Handle credentials safely

Keep the Signals workspace secret in server-side credential storage. Never include it in prompts, URLs, logs, source control, or client-side code. For operation names and request fields, use the Conversion API reference.

Implementation references