{"openapi":"3.1.0","info":{"title":"Partner API","version":"1.1.0","description":"Send merchant deals, track their status, receive webhooks and pull residuals from your own software. Every API key acts as ONE partner account inside ONE organization and can only see that partner's own deals and residuals.\n\nAll requests and responses are JSON with camelCase field names. Money amounts are integer cents in USD.\n\nThis document is the source of truth for the API; the server is tested against it.\n\n**Permissions.** Keys are `read_write` (default) or `read_only`. Read-only keys may call every GET endpoint; any other method returns `403 insufficient_permission`.\n\n**Expiry and rotation.** Keys can carry an expiry date. Rotating a key in the portal issues a replacement and keeps the old key working for a grace period; during that period responses carry `X-Api-Key-Grace-Ends`. Expired keys and rotated keys past their grace period return `401 unauthorized`.\n\n**Request ids.** Every response carries `X-Request-Id`; quote it when asking for support. Requests are listed in the portal's Logs section."},"servers":[{"url":"/api/partner/v1","description":"Relative to the host you use for the partner portal."}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Account"},{"name":"Deals"},{"name":"Merchants","description":"Your merchants that are live. Processors are shown only as anonymized lane labels."},{"name":"Events","description":"Every webhook event, retrievable for 90 days so a missed delivery can be recovered."},{"name":"Residuals"},{"name":"Sandbox","description":"Test-mode only helpers for exercising your integration."},{"name":"Spec"}],"x-rate-limit":{"requestsPerMinutePerKey":120,"headers":["X-RateLimit-Limit","Retry-After"]},"paths":{"/openapi.json":{"get":{"tags":["Spec"],"operationId":"getOpenApiSpec","summary":"Download this API specification","security":[],"responses":{"200":{"description":"This document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"Identify the partner and key","description":"Handy first call to confirm your key works and whether it is live or test.","responses":{"200":{"description":"The partner behind this key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"},"example":{"object":"partner","livemode":false,"partner":{"id":731,"name":"Acme Referral Partners"},"apiKey":{"id":12,"mode":"test"}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/deals":{"post":{"tags":["Deals"],"operationId":"createDeal","summary":"Submit a deal","description":"Creates a merchant lead credited to your partner account, exactly like a portal submission. Only `contactName` is required; unknown fields are ignored. Send an `Idempotency-Key` header so a retried request never creates a duplicate: repeating the same key with the same body returns the original response (with `Idempotent-Replayed: true`); the same key with a different body returns `409 idempotency_conflict`. Test keys create sandbox deals only.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","minLength":1,"maxLength":255},"description":"Unique value per logical deal, e.g. your own record id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealInput"},"example":{"contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550142","monthlyVolume":"45000","averageTicket":"12.50","businessCity":"Miami","businessState":"FL","notes":"Wants countertop terminal"}}}},"responses":{"201":{"description":"Deal created (or replayed).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deal"},"example":{"id":48213,"object":"deal","livemode":true,"status":"received","contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550142","monthlyVolume":"45000","createdAt":"2026-09-01T14:03:11.000Z","updatedAt":"2026-09-03T09:12:40.000Z"}}}},"400":{"description":"Validation failed (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"409":{"description":"Idempotency-Key reused with a different body (`idempotency_conflict`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"get":{"tags":["Deals"],"operationId":"listDeals","summary":"List your deals","description":"Newest first. Page with `cursor` = the previous page's `nextCursor`.","parameters":[{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","schema":{"type":"integer","minimum":1},"description":"Return deals older than this id."},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/DealStatus"}}],"responses":{"200":{"description":"A page of deals.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealList"},"example":{"object":"list","livemode":true,"data":[{"id":48213,"object":"deal","livemode":true,"status":"in_progress","contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550142","monthlyVolume":"45000","createdAt":"2026-09-01T14:03:11.000Z","updatedAt":"2026-09-03T09:12:40.000Z"}],"hasMore":false,"nextCursor":null}}}},"400":{"description":"Invalid query parameter.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/deals/{id}":{"get":{"tags":["Deals"],"operationId":"getDeal","summary":"Get one deal with its status history","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1},"description":"Deal id."}],"responses":{"200":{"description":"The deal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealWithHistory"},"example":{"id":48213,"object":"deal","livemode":true,"status":"in_progress","contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550142","monthlyVolume":"45000","createdAt":"2026-09-01T14:03:11.000Z","updatedAt":"2026-09-03T09:12:40.000Z","history":[{"status":"received","at":"2026-09-01T14:03:11.000Z"},{"status":"in_progress","at":"2026-09-02T16:20:05.000Z"}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"description":"No such deal for this key (`not_found`). Deals belonging to anyone else also return 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}},"patch":{"tags":["Deals"],"operationId":"updateDeal","summary":"Update a deal","description":"Updates fields on a deal you submitted while its status is `received` or `in_progress`. Once the deal reaches `application_submitted` (underwriting) or later, returns `409 deal_locked`. Requires a read-write key. Safe to retry.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1},"description":"Deal id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealPatch"},"example":{"contactPhone":"+13055550199","monthlyVolume":"52000"}}}},"responses":{"200":{"description":"The updated deal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deal"},"example":{"id":48213,"object":"deal","livemode":true,"status":"in_progress","contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550199","monthlyVolume":"52000","createdAt":"2026-09-01T14:03:11.000Z","updatedAt":"2026-09-03T09:12:40.000Z"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DealLocked"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/deals/{id}/withdraw":{"post":{"tags":["Deals"],"operationId":"withdrawDeal","summary":"Withdraw a deal","description":"Withdraws a deal you submitted while it is `received` or `in_progress`; the deal moves to `closed` and a `deal.status_changed` event fires. Idempotent: withdrawing an already-withdrawn deal returns it unchanged. Returns `409 deal_locked` once the deal is in underwriting or later. Requires a read-write key.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1},"description":"Deal id."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WithdrawInput"},"example":{"reason":"Merchant signed elsewhere"}}}},"responses":{"200":{"description":"The withdrawn deal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Deal"},"example":{"id":48213,"object":"deal","livemode":true,"status":"closed","contactName":"Jordan Lee","companyName":"Lee's Coffee Bar","contactEmail":"jordan@leescoffee.example","contactPhone":"+13055550142","monthlyVolume":"45000","createdAt":"2026-09-01T14:03:11.000Z","updatedAt":"2026-09-03T09:12:40.000Z"}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/DealLocked"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/merchants":{"get":{"tags":["Merchants"],"operationId":"listMerchants","summary":"List live merchants","description":"Your merchants that are live, newest first. The processor is an anonymized lane label; real processor names are never returned. Test keys list sandbox deals simulated to `live`.","parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"integer"},"description":"`nextCursor` from the previous page."}],"responses":{"200":{"description":"A page of merchants.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MerchantList"},"example":{"object":"list","livemode":true,"data":[{"object":"merchant","id":912,"livemode":true,"businessName":"Lee's Coffee Bar","dba":"Lee's Coffee","mccCode":"5814","status":"live","processor":"Lane 2","liveSince":"2026-09-20"}],"hasMore":false,"nextCursor":null}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/events":{"get":{"tags":["Events"],"operationId":"listEvents","summary":"List events","description":"Events for this key's partner and mode, newest first. Use it to recover events your webhook endpoint missed. Events are kept for 90 days and are recorded while you hold an API key of that mode.","parameters":[{"name":"type","in":"query","required":false,"schema":{"$ref":"#/components/schemas/EventType"}},{"name":"createdAfter","in":"query","required":false,"schema":{"type":"string","format":"date-time"},"description":"Only events created after this time."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","minimum":1,"maximum":100,"default":25}},{"name":"cursor","in":"query","required":false,"schema":{"type":"string"},"description":"`nextCursor` from the previous page."}],"responses":{"200":{"description":"A page of events.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EventList"},"example":{"object":"list","livemode":true,"data":[{"object":"event","id":"evt_3f9a0c1e8b7d4a2f9e6c5b4a3d2e1f00","type":"deal.status_changed","createdAt":"2026-09-02T16:20:05.000Z","livemode":true,"data":{"deal":{"id":48213,"status":"in_progress","previousStatus":"received","changedAt":"2026-09-02T16:20:05.000Z"}}}],"hasMore":false,"nextCursor":null}}}},"400":{"$ref":"#/components/responses/ValidationError"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/events/{id}":{"get":{"tags":["Events"],"operationId":"getEvent","summary":"Get one event","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Event id (`evt_...`), the same id sent in the webhook body."}],"responses":{"200":{"description":"The event.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StoredEvent"},"example":{"object":"event","id":"evt_3f9a0c1e8b7d4a2f9e6c5b4a3d2e1f00","type":"deal.status_changed","createdAt":"2026-09-02T16:20:05.000Z","livemode":true,"data":{"deal":{"id":48213,"status":"in_progress","previousStatus":"received","changedAt":"2026-09-02T16:20:05.000Z"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/residuals":{"get":{"tags":["Residuals"],"operationId":"listResiduals","summary":"Residuals by month","description":"Monthly totals and per-merchant lines for your account — the same figures as the Earnings view in your partner portal. Defaults to the last 12 months; at most 24 months per request.","parameters":[{"name":"from","in":"query","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-01"},{"name":"to","in":"query","schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-08"}],"responses":{"200":{"description":"Residual report.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResidualReport"},"example":{"object":"residual_report","livemode":true,"currency":"USD","from":"2026-07","to":"2026-08","totals":{"volumeCents":9120000,"earningsCents":22800,"lineCount":2},"months":[{"month":"2026-08","volumeCents":4600000,"earningsCents":11500,"lines":[{"merchantId":9001,"merchantName":"Lee's Coffee Bar","type":"merchant","volumeCents":4600000,"earningsCents":11500}]},{"month":"2026-07","volumeCents":4520000,"earningsCents":11300,"lines":[{"merchantId":9001,"merchantName":"Lee's Coffee Bar","type":"merchant","volumeCents":4520000,"earningsCents":11300}]}]}}}},"400":{"description":"Invalid month range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/residuals/{month}":{"get":{"tags":["Residuals"],"operationId":"getResidualMonth","summary":"Residuals for one month","parameters":[{"name":"month","in":"path","required":true,"schema":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"example":"2026-08"}],"responses":{"200":{"description":"One month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResidualMonthReport"},"example":{"object":"residual_month","livemode":true,"currency":"USD","month":"2026-08","volumeCents":4600000,"earningsCents":11500,"lines":[{"merchantId":9001,"merchantName":"Lee's Coffee Bar","type":"merchant","volumeCents":4600000,"earningsCents":11500}]}}}},"400":{"description":"Invalid month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/sandbox/deals/{id}/simulate":{"post":{"tags":["Sandbox"],"operationId":"simulateDealStatus","summary":"Move a sandbox deal to a status","description":"Test keys only. Changes a sandbox deal's status and fires the same webhooks a real change would (`deal.status_changed`, plus `deal.approved`/`deal.declined`).","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"integer","minimum":1},"description":"Deal id."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"$ref":"#/components/schemas/DealStatus"}}},"example":{"status":"approved"}}}},"responses":{"200":{"description":"The updated sandbox deal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DealWithHistory"}}}},"400":{"description":"Invalid status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Live key used (`test_mode_only`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No such sandbox deal.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}},"/sandbox/residuals/simulate":{"post":{"tags":["Sandbox"],"operationId":"simulateResidualsPosted","summary":"Fire a residuals.posted webhook","description":"Test keys only. Sends a test-mode `residuals.posted` event to your test webhook endpoints.","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"month":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"}}},"example":{"month":"2026-08"}}}},"responses":{"202":{"description":"Event queued.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimulatedEvent"}}}},"400":{"description":"Invalid month.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"description":"Live key used (`test_mode_only`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"$ref":"#/components/responses/RateLimited"},"500":{"$ref":"#/components/responses/InternalError"}}}}},"webhooks":{"deal.created":{"post":{"summary":"A deal credited to you was created.","operationId":"webhook_deal_created","parameters":[{"name":"X-Webhook-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1759075200,v1=5f2b...","description":"`t` = unix seconds; `v1` = hex HMAC-SHA256 of `{t}.{raw body}` with your endpoint's signing secret."},{"name":"X-Webhook-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Webhook-Event","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"type":{"const":"deal.created"},"data":{"$ref":"#/components/schemas/DealEventData"}}}]}}}},"responses":{"2XX":{"description":"Return any 2xx within 10 seconds to acknowledge. Anything else (or a timeout/redirect) is retried with exponential backoff, up to 8 attempts."}},"description":"Fires for every deal credited to you, whatever created it: this API, your portal, your landing pages, chat, referrals, social inboxes, imports or an admin."}},"deal.status_changed":{"post":{"summary":"A deal's public status changed. Moves inside one public status never fire.","operationId":"webhook_deal_status_changed","parameters":[{"name":"X-Webhook-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1759075200,v1=5f2b...","description":"`t` = unix seconds; `v1` = hex HMAC-SHA256 of `{t}.{raw body}` with your endpoint's signing secret."},{"name":"X-Webhook-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Webhook-Event","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"type":{"const":"deal.status_changed"},"data":{"$ref":"#/components/schemas/DealEventData"}}}]}}}},"responses":{"2XX":{"description":"Return any 2xx within 10 seconds to acknowledge. Anything else (or a timeout/redirect) is retried with exponential backoff, up to 8 attempts."}}}},"deal.approved":{"post":{"summary":"A deal moved to approved (also sends deal.status_changed).","operationId":"webhook_deal_approved","parameters":[{"name":"X-Webhook-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1759075200,v1=5f2b...","description":"`t` = unix seconds; `v1` = hex HMAC-SHA256 of `{t}.{raw body}` with your endpoint's signing secret."},{"name":"X-Webhook-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Webhook-Event","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"type":{"const":"deal.approved"},"data":{"$ref":"#/components/schemas/DealEventData"}}}]}}}},"responses":{"2XX":{"description":"Return any 2xx within 10 seconds to acknowledge. Anything else (or a timeout/redirect) is retried with exponential backoff, up to 8 attempts."}}}},"deal.declined":{"post":{"summary":"A deal was declined (also sends deal.status_changed).","operationId":"webhook_deal_declined","parameters":[{"name":"X-Webhook-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1759075200,v1=5f2b...","description":"`t` = unix seconds; `v1` = hex HMAC-SHA256 of `{t}.{raw body}` with your endpoint's signing secret."},{"name":"X-Webhook-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Webhook-Event","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"type":{"const":"deal.declined"},"data":{"$ref":"#/components/schemas/DealEventData"}}}]}}}},"responses":{"2XX":{"description":"Return any 2xx within 10 seconds to acknowledge. Anything else (or a timeout/redirect) is retried with exponential backoff, up to 8 attempts."}}}},"residuals.posted":{"post":{"summary":"Residuals for a month were posted or updated for you.","operationId":"webhook_residuals_posted","parameters":[{"name":"X-Webhook-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"t=1759075200,v1=5f2b...","description":"`t` = unix seconds; `v1` = hex HMAC-SHA256 of `{t}.{raw body}` with your endpoint's signing secret."},{"name":"X-Webhook-Id","in":"header","required":true,"schema":{"type":"string"}},{"name":"X-Webhook-Event","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","properties":{"type":{"const":"residuals.posted"},"data":{"$ref":"#/components/schemas/ResidualsEventData"}}}]}}}},"responses":{"2XX":{"description":"Return any 2xx within 10 seconds to acknowledge. Anything else (or a timeout/redirect) is retried with exponential backoff, up to 8 attempts."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer ptk_live_...` (live) or `ptk_test_...` (test). Create keys in the partner portal under Developer API. The full key is shown once."}},"responses":{"Unauthorized":{"description":"Missing, malformed, revoked, expired or unknown key, or a rotated key past its grace period (`unauthorized`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Forbidden":{"description":"The partner account behind the key is not active (`forbidden`), or a read-only key called a write endpoint (`insufficient_permission`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"RateLimited":{"description":"Too many requests for this key (`rate_limited`). Wait for `Retry-After` seconds.","headers":{"Retry-After":{"schema":{"type":"integer"}},"X-RateLimit-Limit":{"schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"InternalError":{"description":"Unexpected server error (`internal_error`). Safe to retry; use an Idempotency-Key for writes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"DealLocked":{"description":"The deal is in underwriting or later and can no longer be changed through the API (`deal_locked`). `details.status` holds its current status.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"No such resource for this key (`not_found`). Resources belonging to anyone else also return 404.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ValidationError":{"description":"Invalid input (`validation_error`).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"DealStatus":{"type":"string","enum":["received","in_progress","application_submitted","approved","boarding","live","declined","closed"],"description":"Stable public deal status. `received`: submitted, not yet worked. `in_progress`: being worked by the sales team. `application_submitted`: merchant application submitted for underwriting. `approved`: application approved. `boarding`: merchant account being set up. `live`: processing. `declined`: application declined. `closed`: closed without an account (e.g. merchant not interested)."},"ErrorCode":{"type":"string","enum":["unauthorized","forbidden","not_found","validation_error","idempotency_conflict","rate_limited","test_mode_only","insufficient_permission","deal_locked","internal_error"]},"EventType":{"type":"string","enum":["deal.created","deal.status_changed","deal.approved","deal.declined","residuals.posted","webhook.test"]},"ErrorResponse":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"$ref":"#/components/schemas/ErrorCode"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true,"description":"e.g. `{\"field\": \"contactName\"}` for validation errors."}}}},"example":{"error":{"code":"validation_error","message":"Contact name is required (minimum 2 characters)","details":{"field":"contactName"}}}},"Me":{"type":"object","required":["object","livemode","partner","apiKey"],"properties":{"object":{"const":"partner"},"livemode":{"type":"boolean"},"partner":{"type":"object","properties":{"id":{"type":"integer"},"name":{"type":"string"}}},"apiKey":{"type":"object","properties":{"id":{"type":"integer"},"mode":{"type":"string","enum":["live","test"]},"permission":{"$ref":"#/components/schemas/KeyPermission"},"expiresAt":{"type":["string","null"],"format":"date-time"},"graceEndsAt":{"type":["string","null"],"format":"date-time","description":"Set while this key is being rotated out; it stops working at this time."}}}}},"DealInput":{"type":"object","required":["contactName"],"properties":{"contactName":{"type":"string","minLength":2,"maxLength":2000},"contactEmail":{"type":"string","format":"email"},"contactPhone":{"type":"string"},"companyName":{"type":"string"},"monthlyVolume":{"type":"string","description":"Estimated monthly card volume in dollars."},"averageTicket":{"type":"string","description":"Average ticket in dollars."},"mccCode":{"type":"string"},"mccDescription":{"type":"string"},"currentProcessor":{"type":"string"},"cardPresentPercent":{"type":"integer","minimum":0,"maximum":100},"websiteUrl":{"type":"string"},"businessStreet":{"type":"string"},"businessUnit":{"type":"string"},"businessCity":{"type":"string"},"businessState":{"type":"string"},"businessZip":{"type":"string"},"notes":{"type":"string"}},"description":"String fields are limited to 2000 characters. Unknown fields are ignored."},"Deal":{"type":"object","required":["id","object","livemode","status","contactName","createdAt","updatedAt"],"properties":{"id":{"type":"integer"},"object":{"const":"deal"},"livemode":{"type":"boolean","description":"false for sandbox deals created with a test key."},"status":{"$ref":"#/components/schemas/DealStatus"},"contactName":{"type":"string"},"companyName":{"type":["string","null"]},"contactEmail":{"type":["string","null"]},"contactPhone":{"type":["string","null"]},"monthlyVolume":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"DealHistoryEntry":{"type":"object","required":["status","at"],"properties":{"status":{"$ref":"#/components/schemas/DealStatus"},"at":{"type":"string","format":"date-time"}}},"DealWithHistory":{"allOf":[{"$ref":"#/components/schemas/Deal"},{"type":"object","required":["history"],"properties":{"history":{"type":"array","items":{"$ref":"#/components/schemas/DealHistoryEntry"}}}}]},"DealList":{"type":"object","required":["object","livemode","data","hasMore","nextCursor"],"properties":{"object":{"const":"list"},"livemode":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Deal"}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["integer","null"]}}},"ResidualLine":{"type":"object","required":["merchantId","merchantName","type","volumeCents","earningsCents"],"properties":{"merchantId":{"type":["integer","null"]},"merchantName":{"type":["string","null"]},"type":{"type":"string","enum":["merchant","month_total"],"description":"`month_total` lines carry a whole-month amount not broken down by merchant."},"volumeCents":{"type":"integer"},"earningsCents":{"type":"integer","description":"Your earnings for the line."}}},"ResidualMonth":{"type":"object","required":["month","volumeCents","earningsCents","lines"],"properties":{"month":{"type":"string"},"volumeCents":{"type":"integer"},"earningsCents":{"type":"integer"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ResidualLine"}}}},"ResidualReport":{"type":"object","required":["object","livemode","currency","from","to","totals","months"],"properties":{"object":{"const":"residual_report"},"livemode":{"type":"boolean"},"currency":{"const":"USD"},"from":{"type":"string"},"to":{"type":"string"},"totals":{"type":"object","properties":{"volumeCents":{"type":"integer"},"earningsCents":{"type":"integer"},"lineCount":{"type":"integer"}}},"months":{"type":"array","items":{"$ref":"#/components/schemas/ResidualMonth"}}}},"ResidualMonthReport":{"type":"object","required":["object","livemode","currency","month","volumeCents","earningsCents","lines"],"properties":{"object":{"const":"residual_month"},"livemode":{"type":"boolean"},"currency":{"const":"USD"},"month":{"type":"string"},"volumeCents":{"type":"integer"},"earningsCents":{"type":"integer"},"lines":{"type":"array","items":{"$ref":"#/components/schemas/ResidualLine"}}}},"SimulatedEvent":{"type":"object","properties":{"object":{"const":"event"},"livemode":{"const":false},"id":{"type":"string"},"type":{"$ref":"#/components/schemas/EventType"},"data":{"type":"object"}}},"Event":{"type":"object","required":["id","type","createdAt","livemode","data"],"description":"Webhook body. Verify the `X-Webhook-Signature` header before trusting it. Use `id` to ignore duplicates: deliveries are at-least-once.","properties":{"id":{"type":"string","example":"evt_3f9a0c1e8b7d4a2f9e6c5b4a3d2e1f00"},"type":{"$ref":"#/components/schemas/EventType"},"createdAt":{"type":"string","format":"date-time"},"livemode":{"type":"boolean"},"data":{"type":"object"}}},"DealEventData":{"type":"object","properties":{"deal":{"type":"object","properties":{"id":{"type":"integer"},"status":{"$ref":"#/components/schemas/DealStatus"},"previousStatus":{"$ref":"#/components/schemas/DealStatus"},"changedAt":{"type":"string","format":"date-time"},"contactName":{"type":"string"},"companyName":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}}}}},"ResidualsEventData":{"type":"object","properties":{"residuals":{"type":"object","properties":{"month":{"type":"string","example":"2026-08"}}}},"description":"Fetch GET /residuals/{month} for the figures."},"KeyPermission":{"type":"string","enum":["read_only","read_write"],"description":"`read_only` keys may only call GET endpoints."},"DealPatch":{"type":"object","description":"Any subset of the deal input fields. Send an empty string to clear an optional field. `contactName` cannot be cleared.","properties":{"contactName":{"type":"string","minLength":2,"maxLength":2000},"contactEmail":{"type":"string","format":"email"},"contactPhone":{"type":"string"},"companyName":{"type":"string"},"monthlyVolume":{"type":"string","description":"Estimated monthly card volume in dollars."},"averageTicket":{"type":"string","description":"Average ticket in dollars."},"mccCode":{"type":"string"},"mccDescription":{"type":"string"},"currentProcessor":{"type":"string"},"cardPresentPercent":{"type":"integer","minimum":0,"maximum":100},"websiteUrl":{"type":"string"},"businessStreet":{"type":"string"},"businessUnit":{"type":"string"},"businessCity":{"type":"string"},"businessState":{"type":"string"},"businessZip":{"type":"string"},"notes":{"type":"string"}}},"WithdrawInput":{"type":"object","properties":{"reason":{"type":"string","maxLength":500,"description":"Optional note shown to the agent's team."}}},"EventList":{"type":"object","required":["object","livemode","data","hasMore","nextCursor"],"properties":{"object":{"const":"list"},"livemode":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/StoredEvent"}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["string","null"],"description":"Pass as `cursor` to fetch the next (older) page."}}},"StoredEvent":{"allOf":[{"$ref":"#/components/schemas/Event"},{"type":"object","required":["object"],"properties":{"object":{"const":"event"}}}],"description":"The exact event body that was (or would have been) sent to your webhooks."},"Merchant":{"type":"object","required":["object","id","livemode","businessName","status","processor","dealId","liveSince"],"properties":{"object":{"const":"merchant"},"id":{"type":"integer"},"livemode":{"type":"boolean"},"businessName":{"type":"string"},"dba":{"type":["string","null"]},"mccCode":{"type":["string","null"]},"status":{"const":"live"},"processor":{"type":["string","null"],"description":"Anonymized lane label such as `Lane 2`. Never a real processor name.","example":"Lane 2"},"dealId":{"type":["integer","null"],"description":"The id of your deal (from POST /deals) this merchant was boarded from, or null when the merchant is not linked to one of your deals."},"liveSince":{"type":["string","null"],"description":"Boarding date (YYYY-MM-DD) in live mode."}}},"MerchantList":{"type":"object","required":["object","livemode","data","hasMore","nextCursor"],"properties":{"object":{"const":"list"},"livemode":{"type":"boolean"},"data":{"type":"array","items":{"$ref":"#/components/schemas/Merchant"}},"hasMore":{"type":"boolean"},"nextCursor":{"type":["integer","null"]}}}}},"x-changelog":[{"version":"1.1.0","date":"2026-09-29","changes":["Added GET /events and GET /events/{id} to recover missed webhooks.","Added PATCH /deals/{id} and POST /deals/{id}/withdraw (before underwriting only).","Added GET /merchants (live merchants, anonymized processor labels).","Added read-only keys (`insufficient_permission`), key expiry and rotation with a grace period (`X-Api-Key-Grace-Ends`).","Added `deal_locked` error code and `X-Request-Id` on every response.","deal.created now fires for every deal credited to you, whatever created it."]},{"version":"1.0.0","date":"2026-09-15","changes":["Initial release: deals, residuals, webhooks and sandbox."]}]}