openapi: 3.2.0 info: title: Gtm Linkedin Custom Requests API version: '1.0' contact: name: GTM API url: https://gtm-api.com email: support@gtm-api.com license: name: Proprietary url: https://gtm-api.com/license description: 'Operations tagged linkedin_custom_requests across 2 of this provider''s published API definitions: gtm-api-openapi-openapi.yml, gtm-api-linkedin-openapi.yaml. Each path carries the servers of the definition it was published in.' servers: - url: https://app.gtm-api.com/linkedin/v4 description: Production, through the app.gtm-api.com gateway security: - BearerJwt: [] TeamSid: [] tags: - name: linkedin_custom_requests description: Registry package `mcp.linkedin/linkedin_custom_requests`, served on MCP mount `linkedin.platform`. paths: /api/linkedin-custom/execute: post: operationId: execute_linkedin_custom_request summary: Execute custom LinkedIn request (escape hatch) description: 'ESCAPE HATCH: issue one arbitrary LinkedIn HTTP call (url + GET/POST + headers/body) under a chosen OWN account, for endpoints the typed methods do not cover. May be a read or an action (apply to a job, attend an event), so you own the semantics. High-risk: admin-gated + feature-flagged; the url must match the server host allowlist (else 403 forbidden_endpoint). OWN-ACCOUNT ONLY: linkedin_account_sid is REQUIRED. It spends the account''s custom_request bucket, which returns 429 when saturated. A non-2xx response is still a successful dispatch (ok=false, status_code carries it; never throws). The response comes back inline, NOT stored; the audit is the linkedin-account-activity-log row (action_type=custom_request). PREFER TYPED METHODS FIRST: searches/lists → linkedin-scraping; one profile/company/post''s own data → linkedin-enrichment; sends/invites/reactions/comments → messaging & networking. Never use it to route around a rate limit or a missing permission. Contract: - MCP tool `execute_linkedin_custom_request`, registry package `mcp.linkedin/linkedin_custom_requests`, mount `linkedin.platform`. - Operation `action`, response envelope `action`. - Flags: dangerous: the MCP layer gates it behind a preview/commit token, and the effect cannot be undone through this API; paced: a call spends the `custom_request` smart-limit bucket of the account it runs on, and calls of one bucket are spaced per account. A short wait is slept by the server; a longer one answers 429 `rate_limited` with `context.retry_after`, and the same call succeeds from that moment. Parallel calls on one account queue behind each other.' tags: - linkedin_custom_requests requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/ExecuteLinkedinCustomRequestRequest' responses: '200': description: '`action` success envelope.' content: application/json: schema: $ref: '#/components/schemas/ExecuteLinkedinCustomRequestResponse' 4XX: $ref: '#/components/responses/McpClientError' 5XX: $ref: '#/components/responses/McpServerError' x-gtm-mcp-tool: execute_linkedin_custom_request x-gtm-mcp-mount: linkedin.platform x-gtm-entity: linkedin_custom_requests x-gtm-operation: action x-gtm-envelope: action x-gtm-availability: ga x-gtm-dangerous: true x-gtm-mass-action: false x-gtm-step-eligible: false x-gtm-schedule-required: false x-gtm-tool-class: complex x-gtm-paced-bucket: custom_request servers: - url: https://app.gtm-api.com/linkedin/v4 description: Production, through the app.gtm-api.com gateway components: schemas: ExecuteLinkedinCustomRequestResponse: type: object properties: success: type: boolean enum: - true operation: type: string enum: - action action: type: string description: kebab-case verb; matches the route segment. item: {} result: type: object properties: status_code: type: integer description: 'The HTTP status the plugin observed: ANY value; the verb never throws on non-2xx.' ok: type: boolean description: true iff status_code ∈ [200,299]. headers: type: object additionalProperties: type: string description: Response headers the plugin observed. body: description: Parsed response body (JSON when parseable, else raw string). Returned inline, NOT persisted at rest. activity_log: type: object properties: {} description: Full dispatch row (linkedin-account-activity-log, action_type=custom_request) per §4.12a. required: - status_code - ok - headers - activity_log meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms pacing: type: object properties: linkedin_account_sid: type: string description: The account whose bucket the call spent. limit_type: type: string description: The smart-limit bucket the call spent, e.g. send_messages. next_call_after: type: string description: 'ISO 8601, the same form as retry_after: the moment this same call goes through again without waiting. The next pacing slot while the day has budget left, the daily reset when it has none, the end of a LinkedIn lock while one stands.' remaining_today: type: integer minimum: 0 description: daily_limit minus done_today_count of that bucket, after this call. required: - linkedin_account_sid - limit_type - next_call_after - remaining_today required: - success - operation - action - item - result - meta McpError: type: object properties: success: type: boolean enum: - false error: type: object properties: code: type: string enum: - validation_failed - nothing_to_update - not_found - relation_not_found - invalid_transition - limit_exceeded - payment_required - duplicate_rejected - conflict - delete_blocked - unauthorized - forbidden - rate_limited - internal_error - service_unavailable - not_implemented message: type: string recoverable: type: boolean suggestion: type: string field_errors: type: object additionalProperties: type: array items: type: object properties: rule: type: string message: type: string required: - rule - message blockers: type: array items: type: object properties: type: type: string description: Machine-readable blocker type (active_flow, pending_tasks, …). severity: type: string enum: - hard - soft description: hard = external action required; soft = acknowledge is enough. description: type: string entity_sid: type: - string - 'null' count: type: integer resolution: type: string description: 'Hard: tool name to call. Soft: code for acknowledge[].' resolution_hint: type: string required: - type - severity - description - entity_sid - resolution - resolution_hint context: type: object additionalProperties: {} required: - code - message - recoverable meta: type: object properties: trace_id: type: string description: UUID v7; same 128-bit value as the X-Trace-Id header. span_id: type: string pattern: ^[0-9a-f]{16}$ description: 16 hex chars, root span of this request. timestamp: type: string description: ISO 8601 UTC (Y-m-dTH:i:sZ), response time. duration_ms: type: integer minimum: 0 description: Server-side wall clock. team_sid: type: - string - 'null' description: The team this call ran in (the token team, or the team_sid override). Null when unauthenticated; absent from pre-2026-08-20 backends. actor_type: type: - string - 'null' description: user | agent | api_key | system. Null when unauthenticated; absent from pre-2026-08-20 backends. required: - trace_id - span_id - timestamp - duration_ms required: - success - error ExecuteLinkedinCustomRequestRequest: type: object description: Request body of `execute_linkedin_custom_request`. properties: linkedin_account_sid: type: string minLength: 18 maxLength: 18 pattern: ^ln_ac_ description: 'REQUIRED executor: the OWN account (ln_ac_…) the call runs as. Every custom request runs on the account named here, carrying that account''s session, permissions and limits, so name the account whose identity the request should carry. There is no default and no substitute: omit it and the call is rejected.' url: type: string minLength: 1 maxLength: 2048 description: 'Absolute LinkedIn URL (e.g. "https://www.linkedin.com/voyager/api/…") or a bare path (resolved against https://www.linkedin.com). MUST match the server host + path allowlist (provisional: *.linkedin.com + path prefixes /voyager/api/, /sales-api/). Otherwise 403 forbidden_endpoint.' method: type: string enum: - GET - POST description: HTTP verb, default GET. Write-shaped verbs (PUT/DELETE/PATCH) are out of scope at launch (SAFETY). headers: type: object additionalProperties: type: string description: Extra request headers merged onto the default voyager headers. body: anyOf: - type: object additionalProperties: {} - type: string - {} description: POST JSON body (object → JSON-encoded) or raw string (passed through); ≤ 50 KB serialized; null/omitted for GET. form: type: boolean description: 'Modifier: when true, send `body` as application/x-www-form-urlencoded (NOT a separate body). POST only.' include_default_headers: type: boolean description: Inject the plugin's default voyager headers (default true); false to send only `headers`. required: - linkedin_account_sid - url responses: McpServerError: description: MCP error envelope with `error.code` internal_error or service_unavailable. content: application/json: schema: $ref: '#/components/schemas/McpError' McpClientError: description: MCP error envelope. `error.code` is one of validation_failed, nothing_to_update, not_found, relation_not_found, invalid_transition, limit_exceeded, payment_required, duplicate_rejected, conflict, delete_blocked, unauthorized, forbidden, rate_limited, not_implemented. content: application/json: schema: $ref: '#/components/schemas/McpError' securitySchemes: BearerJwt: type: http scheme: bearer bearerFormat: JWT description: Access token issued by gtm.service.id. Its `access_identity` claim carries `team_sid`, `actor_sid` and `actor_type`, and that team scope is authoritative. TeamSid: type: apiKey in: header name: Team-SID description: Team scope for tokens that do not carry one. Ignored when the token already names a team. x-refined-from: - gtm-api-openapi-openapi.yml - gtm-api-linkedin-openapi.yaml