Gateman
Documentation/Use PayPal

Use PayPal

capability_id: paypal:use
display_name: Use PayPal
ui_capability_key: use_paypal
scope: paypal:use
endpoint:
  method: POST
  path: /paypal/request
operation: paypal.request
billable: true
environments:
  - production
  - staging
  - development

Purpose and authorization

paypal:use authorizes an authenticated, application-scoped relay for supported native PayPal REST API requests. The application MUST use Contract v1 and the paypal:use scope.

Gateman authenticates and authorizes the application, selects configured PayPal credentials for the requested environment, obtains or reuses a PayPal OAuth access token, executes the native request, returns the provider response within this transport contract, and accounts for the admitted operation. Credentials and access tokens are not returned to callers. This capability does not imply secrets:read.

This is a native API relay, not a complete payment-processing or merchant-management application. PayPal remains authoritative for native permissions, resource states, and payment processing.

Implementation contract

The outer request is an authenticated Gateman JSON request. Its body contains the nested native PayPal request; the outer envelope is not sent to PayPal.

POST /paypal/request
Content-Type: application/json
X-GM-App: app_example
X-GM-Ts: 1791748800
X-GM-Sig: <Contract-v1-signature>
X-GM-Idempotency-Key: optional-gateman-key

Example native Orders request with fictitious data:

{
  "environment": "staging",
  "method": "POST",
  "path": "/v2/checkout/orders",
  "headers": {
    "PayPal-Request-Id": "example-order-001",
    "Prefer": "return=representation"
  },
  "body": {
    "intent": "CAPTURE",
    "purchase_units": [{"amount": {"currency_code": "USD", "value": "10.00"}}]
  }
}

PayPal still validates native operation requirements, account permissions, and resource state.

Request envelope

FieldRequiredContract
environmentYesString, trimmed and lowercased; production, staging, or development.
pathYesRelative string beginning /v1/ or /v2/.
methodNoNative method; defaults to POST; GET, POST, PUT, PATCH, or DELETE.
bodyNoArray/object serialized as JSON, or a JSON string; omitted/null becomes empty.
headersNoMap of supported native headers; omitted/null becomes empty.

Unknown top-level fields are currently ignored; integrations SHOULD send only documented fields. Invalid outer JSON, environment, method, path, body, or headers is rejected before the provider request. There is no distinct PayPal-specific total outer-envelope limit.

Request methods and paths

The nested method MUST be GET, POST, PUT, PATCH, or DELETE; the default is POST. The path MUST begin with /v1/ or /v2/, be no more than 2,048 bytes, and MAY include a query string. Absolute URLs, schemes, hosts, control characters, spaces, #, <, >, quotation marks, backslashes, .., and // are rejected. /v1/oauth2/token cannot be called as a customer relay path.

Gateman selects a fixed PayPal origin by environment. It does not maintain a business-resource allowlist and does not guarantee every PayPal operation works through this JSON transport. There is no general multipart/file-upload contract, arbitrary binary request-body contract, public streaming-response interface, automatic pagination, or higher-level payment orchestration.

Native PayPal JSON serialization

  • Arrays and objects are JSON-encoded.
  • Omitted/null body and empty string become an empty provider body.
  • A non-empty string MUST contain valid JSON and is forwarded unchanged.
  • Other scalar body values are invalid.
  • The serialized nested body MUST be no larger than 4 MiB (4,194,304 bytes).
  • A non-empty body without Content-Type receives application/json.
  • A supplied supported Content-Type is preserved.

JSON Patch arrays are representable where the selected PayPal operation expects them. PayPal validates native fields and business semantics. An invalid or oversized nested body returns HTTP 400 before operation reservation.

Native request headers

Only these caller-provided nested headers are supported:

  • Content-Type
  • Accept
  • PayPal-Request-Id
  • Prefer

Names are matched case-insensitively. Values MUST be strings of no more than 512 bytes and MUST NOT contain CR or LF. Unsupported headers are rejected, including Authorization, PayPal-Auth-Assertion, and PayPal-Partner-Attribution-Id. Gateman constructs Authorization: Bearer from its internally obtained token.

Environment and credential selection

Gateman environmentPayPal API originCredential selected
productionhttps://api-m.paypal.comConfigured production client ID and secret
staginghttps://api-m.sandbox.paypal.comConfigured Sandbox client ID and secret
developmenthttps://api-m.sandbox.paypal.comConfigured Sandbox client ID and secret

Staging and development make genuine PayPal Sandbox requests and may create or modify Sandbox resources. They are not local simulation modes. The selected credentials establish the PayPal account context; Gateman does not provide a merchant selector, provision business accounts, or connect arbitrary sellers.

OAuth token handling and failure boundaries

Gateman uses PayPal client-credentials OAuth, reuses an eligible cached token, securely caches tokens by application and environment, obtains a replacement when needed, and invalidates its cached token after a customer API HTTP 401. It does not replay that customer request and never exposes the token.

OAuth failure is distinct from customer API failure. Credential or OAuth rejection may prevent the customer request. OAuth rate limiting can return HTTP 429; OAuth service failure can return HTTP 503; OAuth transport failure returns HTTP 502; OAuth rejection can return HTTP 502. When these occur after reservation, the admitted operation is consumed.

Native response contract and size limits

Within the limit, Gateman preserves PayPal's status and body and forwards only these selected headers: Content-Type, Location, Retry-After, PayPal-Debug-Id, PayPal-Request-Id, Correlation-Id, and X-Request-Id.

Native 201, 204, 4xx, and 5xx responses, empty bodies, and non-JSON bodies are preserved. Redirects are not followed. Gateman does not wrap ordinary PayPal responses in an ok envelope and does not forward unlisted headers. Official clients may decode responses differently.

Decoded response-body limit

The maximum decoded customer response is 4 MiB (4,194,304 bytes), measured after HTTP decompression and regardless of PayPal status. Exactly 4,194,304 bytes is accepted. A larger compressed, uncompressed, or unknown-length body is rejected while received, before full materialization, with no partial body:

HTTP/1.1 502 Bad Gateway
Content-Type: application/json; charset=utf-8
{"ok":false,"error":"paypal_response_too_large"}

This is a Gateman transport error, not a PayPal rejection. PayPal may already have processed a mutation, so it is not a safe-to-retry signal. The separate outbound nested request-body limit is also 4 MiB; neither limit is an explicit outer-envelope limit.

Idempotency and retry obligations

The optional outer X-GM-Idempotency-Key participates in Contract v1 signing, but does not create a PayPal relay idempotency record, deduplicate execution, replay responses, or prevent additional operation accounting.

The nested PayPal-Request-Id is forwarded and provides PayPal-native idempotency where supported by the selected operation. Its semantics and retention are PayPal-defined, and Gateman does not generate it. It is not universal protection for every method or resource.

Gateman does not automatically retry customer requests. Repeated invocations may reach PayPal again and consume separate Gateman operations. After a timeout, transport failure, missing response, or oversized response, the application MUST NOT assume a mutation did not execute. Use native PayPal-Request-Id where supported and reconcile before retrying; do not blindly retry payments, captures, or refunds. See Idempotency.

Operation accounting and concurrency

The billable operation is paypal.request. One operation is reserved for one admitted Gateman relay invocation. Authentication, validation, admission rejection, and monthly allowance rejection before reservation do not consume an operation. After reservation, missing credentials, OAuth errors, native PayPal errors, rate limits, transport failures, timeouts, and oversized responses consume the reserved operation. A repeated admitted invocation consumes a separate operation.

Admission rejection may return HTTP 429 with applicable retry guidance; admission-control unavailability returns HTTP 503. Monthly allowance exhaustion returns HTTP 403, and accounting unavailability returns HTTP 503. Native PayPal HTTP 429 is provider-originated and distinct from Gateman admission errors. PayPal's native Retry-After is forwarded when supplied.

Errors and uncertain outcomes

ConditionHTTP responseConsequence
Contract v1 authentication failure or missing scope401Gateman rejection; no operation.
Invalid JSON, environment, path, method, body, or headers400Validation rejection; no operation.
Oversized nested request body400Validation rejection; no operation.
Concurrency rejection429 with applicable guidanceGateman admission rejection; no operation.
Admission guard unavailable503No operation reserved.
Monthly allowance exhausted403No new operation reserved.
Accounting unavailable503No confirmed operation; PayPal execution is not established.
Missing credentials after reservation502Operation consumed; customer execution not established.
OAuth rejection/transport failure502Operation consumed; customer execution not established.
OAuth rate limiting429Operation consumed; follow OAuth guidance.
OAuth service failure503Operation consumed; customer execution not established.
Native PayPal response within limitPayPal's status/bodyOperation consumed; interpret PayPal response.
Native PayPal 401Native 401Operation consumed; cache invalidated; no replay.
Native PayPal 429Native 429Operation consumed; follow PayPal guidance.
Customer timeout/transport failure502Operation consumed; execution may be uncertain.
Decoded response over 4 MiB502, paypal_response_too_largeOperation consumed; no partial body; execution may be uncertain.
Unexpected post-reservation exception502, PayPal provider unavailableOperation is consumed; PayPal execution may be uncertain.

See Errors and responses and Authentication for shared rules. Ordinary PayPal responses remain native.

Payment lifecycle and webhook responsibilities

Use PayPal does not provide checkout UI, approval handling, order orchestration, capture/refund reconciliation, subscription activation, vaulting, settlement reporting, generic payment-state persistence, merchant selection, or payment completion guarantees. A successful API response is not necessarily proof of approval, capture, settlement, or fulfilment; applications interpret native PayPal states.

Gateman does not provision or receive PayPal webhooks through this capability. Applications configure subscriptions, receive and authenticate events, handle duplicates and retries, persist outcomes, and reconcile payment state. Gateman Stripe webhook provisioning does not apply to PayPal. See Webhooks and event handling.

Official clients and WordPress boundary

The official PHP, Node.js, Python, and Go clients can invoke /paypal/request through generic authenticated request methods. They handle Contract v1 signing and configured environment injection and do not automatically retry PayPal requests. No dedicated PayPal helper or canonical client is required.

The current WordPress plugin has no dedicated PayPal checkout or payment gateway integration through Gateman. Its Stripe payment gateways do not provide PayPal functionality.

Data handling and retention

Gateman stores application-scoped PayPal client credentials and securely caches OAuth tokens for reuse and expiry handling. Tokens are not exposed to callers. Native request and response bodies are not intentionally persisted by the relay. Gateman has no PayPal-specific transaction ledger or response-replay cache; operation accounting is separate from PayPal business state, and diagnostics omit credentials and payloads. Provider retention belongs to PayPal. See Data retention.

Implementation outcome

A correct integration authenticates with Contract v1 and paypal:use, targets POST /paypal/request, selects the intended environment, supplies valid native JSON and supported headers, relies on Gateman OAuth, preserves native statuses and bodies, distinguishes OAuth from customer failures, uses PayPal-Request-Id where appropriate, does not mistake X-GM-Idempotency-Key for provider idempotency, handles uncertain/oversized responses without unsafe retries, accounts for one paypal.request operation per admitted invocation, and manages payment state and webhooks independently.

Implementation instructions for agents

  • SHOULD use an official Gateman PHP, Node.js, Python, or Go client where suitable; direct HTTP MUST follow Contract v1.
  • MUST use paypal:use, POST /paypal/request, and a supported environment.
  • MUST use only the supported methods and relative /v1/ or /v2/ paths.
  • MUST NOT call PayPal OAuth through the public relay.
  • MUST provide valid native JSON and use only supported nested headers.
  • MUST NOT override provider Authorization.
  • MUST use PayPal-Request-Id where native idempotency is required and supported, and MUST NOT rely on X-GM-Idempotency-Key for deduplication.
  • MUST distinguish OAuth/customer errors and MUST NOT assume automatic retries or blindly retry uncertain mutations.
  • MUST respect both 4 MiB limits; an oversized decoded response returns HTTP 502 paypal_response_too_large without partial content.
  • MUST account for one paypal.request operation per admitted invocation.
  • MUST NOT assume Gateman manages webhooks, settlement, or final payment state, or alter credentials/payment workflows without authorization.

Reusable AGENTS.md block

<!-- gateman:begin capability=paypal:use -->
- Use authenticated Contract v1 with `paypal:use` and target `POST /paypal/request`.
- Include `environment`: `production` uses configured PayPal live credentials;
  `staging` and `development` use configured PayPal Sandbox credentials and
  make real Sandbox requests.
- Use only `GET`, `POST`, `PUT`, `PATCH`, or `DELETE` with a relative `/v1/` or
  `/v2/` path. Do not call PayPal OAuth through the relay.
- Represent the native body as JSON. The nested request and decoded response
  bodies are each limited to 4 MiB (4,194,304 bytes).
- Use only `Content-Type`, `Accept`, `PayPal-Request-Id`, and `Prefer` as
  nested headers. Gateman manages application-scoped OAuth bearer access.
- Use `PayPal-Request-Id` for provider idempotency where supported. Do not
  treat `X-GM-Idempotency-Key` as PayPal deduplication; Gateman does not retry
  PayPal requests automatically.
- Account for one `paypal.request` operation per admitted invocation, including
  provider errors, transport failures, and oversized responses.
- A decoded response over 4 MiB returns HTTP 502
  `paypal_response_too_large` without partial content; PayPal may nevertheless
  have executed the request, so this is not a safe-to-retry signal.
- Preserve and interpret native PayPal status/body and distinguish OAuth from
  customer API failures. Do not blindly retry uncertain mutations.
- Payment lifecycle, reconciliation, webhook configuration, receipt, and
  verification remain customer application responsibilities.
- Full capability reference: https://docs.getgateman.com/capabilities/paypal.use/
<!-- gateman:end capability=paypal:use -->