Skip to content
Syncline

Stripe API reference

<p>This page covers the Syncline endpoints for the Stripe connector. They live on the Syncline API, take a Syncline key, and return the Syncline response shape. Nothing here documents Stripe's own API, and none of these paths exist on Stripe's side: read Stripe's developer documentation when you need the vendor routes.</p><p>Money gets handled explicitly. Stripe reports amounts in minor units, so a charge of forty nine dollars arrives as 4900, and every response below carries both the raw integer and the decimal we derived from it with the currency named. Read routes are available on any connection. Write routes that move money exist only when a flow you built includes them, and they are listed on that flow before you turn it on.</p>
Base URL: https://api.syncline.topclb.com

Authentication

Send a Syncline secret key as a bearer token: Authorization: Bearer sk_live_... . The connection_id parameter selects a Stripe account connected through Stripe Connect, which gives Syncline a restricted key rather than your secret key. Test mode and live mode are separate connections, so a test run can never touch a live account by accident.

Endpoints

<article class="sy-endpoint"><h3><code>GET /v1/connectors/stripe/charges</code></h3><p>List charges with both the raw minor unit amount and the converted decimal.</p><div class="sy-table-wrap"><table><thead><tr><th>Param</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td>connection_id</td><td>string</td><td>yes</td><td>The connected Stripe account to read from.</td></tr><tr><td>status</td><td>string</td><td>no</td><td>One of succeeded, pending or failed. Omit for all three.</td></tr><tr><td>created_after</td><td>string</td><td>no</td><td>ISO 8601 timestamp. Charges created at or after this moment.</td></tr><tr><td>customer_email</td><td>string</td><td>no</td><td>Restrict to one customer, matched on the email on the customer object.</td></tr><tr><td>limit</td><td>integer</td><td>no</td><td>Results per page, 1 to 100. Defaults to 25.</td></tr></tbody></table></div><pre><code>{ &quot;run_id&quot;: &quot;run_a3751f3e&quot;, &quot;connector&quot;: &quot;stripe&quot;, &quot;status&quot;: &quot;ok&quot;, &quot;data&quot;: [ { &quot;charge_id&quot;: &quot;ch_3Q1v8kF2mNpLx0Ab&quot;, &quot;amount_minor&quot;: 4900, &quot;amount&quot;: &quot;49.00&quot;, &quot;currency&quot;: &quot;usd&quot;, &quot;status&quot;: &quot;succeeded&quot;, &quot;customer_email&quot;: &quot;lena@harbourline.example&quot;, &quot;created&quot;: &quot;2026-09-07T06:12:44Z&quot; } ], &quot;next_cursor&quot;: null }</code></pre></article><article class="sy-endpoint"><h3><code>POST /v1/connectors/stripe/customers</code></h3><p>Create a customer, or return the existing one when the email already exists.</p><div class="sy-table-wrap"><table><thead><tr><th>Param</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td>connection_id</td><td>string</td><td>yes</td><td>The connected Stripe account to write to.</td></tr><tr><td>email</td><td>string</td><td>yes</td><td>The customer email. Used as the match key when on_conflict is return_existing.</td></tr><tr><td>name</td><td>string</td><td>no</td><td>Display name for the customer record.</td></tr><tr><td>metadata</td><td>object</td><td>no</td><td>Your own reference IDs. Writing the source record ID here makes reconciliation trivial later.</td></tr><tr><td>on_conflict</td><td>string</td><td>no</td><td>One of return_existing or create. Defaults to return_existing.</td></tr></tbody></table></div><pre><code>{ &quot;run_id&quot;: &quot;run_b486204f&quot;, &quot;connector&quot;: &quot;stripe&quot;, &quot;status&quot;: &quot;ok&quot;, &quot;data&quot;: { &quot;customer_id&quot;: &quot;cus_QpR7t2LmXv90Ka&quot;, &quot;action&quot;: &quot;returned_existing&quot;, &quot;email&quot;: &quot;lena@harbourline.example&quot;, &quot;metadata&quot;: { &quot;hubspot_contact_id&quot;: &quot;701842933&quot; } } }</code></pre></article><article class="sy-endpoint"><h3><code>GET /v1/connectors/stripe/customers</code></h3><p>Find a customer by email so a later step updates instead of duplicating.</p><div class="sy-table-wrap"><table><thead><tr><th>Param</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td>connection_id</td><td>string</td><td>yes</td><td>The connected Stripe account to search.</td></tr><tr><td>email</td><td>string</td><td>yes</td><td>Exact email match, compared after trimming and lowercasing.</td></tr><tr><td>include_subscriptions</td><td>boolean</td><td>no</td><td>Return the customer's active subscriptions alongside the record. Defaults to false.</td></tr></tbody></table></div><pre><code>{ &quot;run_id&quot;: &quot;run_c5973156&quot;, &quot;connector&quot;: &quot;stripe&quot;, &quot;status&quot;: &quot;ok&quot;, &quot;data&quot;: [ { &quot;customer_id&quot;: &quot;cus_QpR7t2LmXv90Ka&quot;, &quot;email&quot;: &quot;lena@harbourline.example&quot;, &quot;created&quot;: &quot;2026-04-18T09:02:31Z&quot;, &quot;delinquent&quot;: false, &quot;subscriptions&quot;: [] } ] }</code></pre></article><article class="sy-endpoint"><h3><code>POST /v1/connectors/stripe/invoices</code></h3><p>Draw up an invoice with line items, left as a draft or finalised.</p><div class="sy-table-wrap"><table><thead><tr><th>Param</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td>connection_id</td><td>string</td><td>yes</td><td>The connected Stripe account to write to.</td></tr><tr><td>customer_id</td><td>string</td><td>yes</td><td>The customer the invoice belongs to.</td></tr><tr><td>line_items</td><td>array</td><td>yes</td><td>Objects with description, amount_minor and quantity. Amounts are integers in minor units.</td></tr><tr><td>currency</td><td>string</td><td>yes</td><td>Three letter code such as usd. Zero decimal currencies are handled without a false division.</td></tr><tr><td>finalize</td><td>boolean</td><td>no</td><td>Finalise and send the invoice. Defaults to false, which leaves a draft for a person to check.</td></tr></tbody></table></div><pre><code>{ &quot;run_id&quot;: &quot;run_d6a84267&quot;, &quot;connector&quot;: &quot;stripe&quot;, &quot;status&quot;: &quot;ok&quot;, &quot;data&quot;: { &quot;invoice_id&quot;: &quot;in_1Q2xR8F2mNpLx0Cd&quot;, &quot;customer_id&quot;: &quot;cus_QpR7t2LmXv90Ka&quot;, &quot;total_minor&quot;: 9800, &quot;total&quot;: &quot;98.00&quot;, &quot;currency&quot;: &quot;usd&quot;, &quot;state&quot;: &quot;draft&quot;, &quot;hosted_invoice_url&quot;: null } }</code></pre></article><article class="sy-endpoint"><h3><code>GET /v1/connectors/stripe/events</code></h3><p>Read the payment events the connector received, for replay or reconciliation.</p><div class="sy-table-wrap"><table><thead><tr><th>Param</th><th>Type</th><th>Required</th><th>Description</th></tr></thead><tbody><tr><td>connection_id</td><td>string</td><td>yes</td><td>The connected Stripe account whose events you want.</td></tr><tr><td>type</td><td>string</td><td>no</td><td>Filter to one type, such as payment.succeeded, payment.failed or refund.issued.</td></tr><tr><td>since</td><td>string</td><td>no</td><td>ISO 8601 timestamp. Events are retained for 30 days on paid plans.</td></tr><tr><td>limit</td><td>integer</td><td>no</td><td>Results per page, 1 to 200. Defaults to 50.</td></tr></tbody></table></div><pre><code>{ &quot;run_id&quot;: &quot;run_e7b95378&quot;, &quot;connector&quot;: &quot;stripe&quot;, &quot;status&quot;: &quot;ok&quot;, &quot;data&quot;: [ { &quot;event_id&quot;: &quot;evt_9c14ba&quot;, &quot;type&quot;: &quot;payment.failed&quot;, &quot;charge_id&quot;: &quot;ch_3Q1v9nF2mNpLx0Zz&quot;, &quot;amount_minor&quot;: 4900, &quot;amount&quot;: &quot;49.00&quot;, &quot;currency&quot;: &quot;usd&quot;, &quot;decline_reason&quot;: &quot;insufficient_funds&quot;, &quot;observed_at&quot;: &quot;2026-09-07T06:41:52Z&quot; } ], &quot;next_cursor&quot;: null }</code></pre></article>

Errors

<div class="sy-table-wrap"><table><thead><tr><th>Code</th><th>Meaning</th><th>What to do</th></tr></thead><tbody><tr><td>401 connection_revoked</td><td>The Stripe Connect authorisation was withdrawn, so the restricted key no longer works.</td><td>Reconnect the account from Connections. Events that arrived while it was down are still in the 30 day window.</td></tr><tr><td>403 write_scope_missing</td><td>This connection holds read scopes only, and the call tried to create an object.</td><td>Reauthorise and approve the write scopes the flow needs. Read only is the default on purpose.</td></tr><tr><td>404 customer_not_found</td><td>No customer matches the ID or email supplied, often because the call ran against the wrong mode.</td><td>Confirm the connection is the live one rather than the test one, then check the email for a typo.</td></tr><tr><td>422 currency_mismatch</td><td>Line items carry a different currency from the invoice, which Stripe will not accept.</td><td>Send one currency per invoice. Split mixed currency line items into separate invoices.</td></tr><tr><td>429 upstream_rate_limited</td><td>Stripe throttled the request, which normally only happens during a large historical read.</td><td>Lower the page size and honour retry_after. Live flows use pushed events, so they rarely reach this.</td></tr></tbody></table></div>

Rate limits

Syncline allows 120 requests per minute per API key. Stripe allows roughly 100 read requests per second in live mode, and the connector works from pushed events rather than polling, so that budget stays almost entirely free for your own calls. Historical reads during a backfill are the one place it matters: page at 100 records and honour retry_after.

Code samples

<h4>curl</h4><pre><code>curl -G https://api.syncline.topclb.com/v1/connectors/stripe/charges \ -H &quot;Authorization: Bearer $SYNCLINE_KEY&quot; \ --data-urlencode &quot;connection_id=con_stripe_8w2&quot; \ --data-urlencode &quot;status=failed&quot; \ --data-urlencode &quot;created_after=2026-09-01T00:00:00Z&quot;</code></pre><h4>node</h4><pre><code>const url = new URL( &quot;https://api.syncline.topclb.com/v1/connectors/stripe/charges&quot; ); url.searchParams.set(&quot;connection_id&quot;, &quot;con_stripe_8w2&quot;); url.searchParams.set(&quot;status&quot;, &quot;failed&quot;); const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.SYNCLINE_KEY}` } }); const { data } = await res.json(); for (const c of data) { console.log(`${c.amount} ${c.currency} ${c.customer_email}`); }</code></pre><h4>python</h4><pre><code>import os import requests resp = requests.get( &quot;https://api.syncline.topclb.com/v1/connectors/stripe/charges&quot;, headers={&quot;Authorization&quot;: f&quot;Bearer {os.environ['SYNCLINE_KEY']}&quot;}, params={&quot;connection_id&quot;: &quot;con_stripe_8w2&quot;, &quot;status&quot;: &quot;failed&quot;}, timeout=30, ) resp.raise_for_status() for charge in resp.json()[&quot;data&quot;]: print(charge[&quot;amount&quot;], charge[&quot;currency&quot;], charge[&quot;customer_email&quot;])</code></pre>