Skip to main content

Ramp

The Ramp source syncs data from the Ramp Developer API for a single Ramp business. It covers card spend (cards, transactions, and reimbursements), your organization and spend controls (users, departments, locations, entities, business details, funds, and spend programs), and accounts payable and procurement (bills, vendors, receipts, merchants, and purchase orders).

Prerequisites​

  • A Ramp account with administrator access, so you can create a developer app.
  • A Ramp developer app that uses the Client Credentials grant type, with the transactions:read, cards:read, and reimbursements:read scopes enabled, plus the read scope for each other stream you want to sync. See Supported Streams for the scope each stream needs.
  • The client ID and client secret for that app.

Setup guide​

Create a developer app in Ramp, then create the source in Airbyte with the app's client ID and client secret.

Set up Ramp​

  1. In your Ramp account, go to Company > Developer.
  2. Select Create New App, name the app, and accept the terms.
  3. Under Grant types, select Add new grant type > Client Credentials. The connector authenticates server-to-server, so it doesn't use the authorization code flow and doesn't need a redirect URI.
  4. Under Scopes, select Configure allowed scopes. Enable transactions:read, cards:read, and reimbursements:read, and the read scope for every other stream you plan to sync.
  5. Copy the client ID and client secret.

For more detail, see Ramp's quickstart and authorization guide.

Set up the Ramp connector in Airbyte​

  1. Log into your Airbyte Cloud account or open your self-managed Airbyte instance.
  2. Click Sources and then click + New source.
  3. On the Set up the source page, select Ramp from the Source type dropdown.
  4. Enter a name for the Ramp connector.
  5. Enter the Ramp Client ID and Ramp Client Secret from your developer app.
  6. Optionally, set Start Date. See Start Date.
  7. Click Set up source.

Connector settings​

Start Date​

On the first sync, the transactions and reimbursements streams only read records with an updated_at on or after this date, and the receipts stream only reads receipts created on or after this date. Later syncs use the saved cursor instead. Other streams ignore Start Date, including vendors, which reads every vendor on its first sync. If you leave it empty, the connector uses 2019-01-01T00:00:00Z.

Enter Start Date as a UTC timestamp with a Z suffix, such as 2024-01-01T00:00:00Z. Fractional seconds, such as 2024-01-01T00:00:00.000Z, are accepted. Values with a numeric offset, such as 2024-01-01T00:00:00+00:00, are rejected.

Connection test​

The connection test only reads the transactions stream. If your app is missing the scope for another stream, the test still passes, and that stream fails during the sync.

Test against the Ramp sandbox​

The connector calls https://api.ramp.com by default. Since version 0.0.4, an API Base URL (api_url) field can point it at Ramp's sandbox at https://demo-api.ramp.com instead. The value must start with https://. Leave the default for production accounts.

The field is hidden in the Airbyte UI, so set it programmatically. For example, include it in the source configuration you send through the Airbyte API, Terraform provider, or PyAirbyte. Sandbox and production credentials aren't interchangeable: create a developer app in the sandbox (https://demo.ramp.com) with the same grant type and scopes, and use that app's client ID and secret with the sandbox base URL.

Supported sync modes​

The Ramp source connector supports the following sync modes:

Only transactions, reimbursements, receipts, and vendors support incremental syncs. Every other stream re-reads all records on every sync.

  • Incremental syncs filter on the server. For transactions and reimbursements, the connector sends the cursor as the updated_after query parameter. Ramp doesn't list updated_after in its published parameters for the transactions endpoint, but in testing the API honors it. If Ramp ever stopped honoring it, each sync would re-read every transaction: you would get duplicate rows, not missing ones. For receipts, the connector sends the cursor as created_after. For vendors, it sends the saved cursor as from_updated_at. A full refresh or a first incremental sync of vendors sends no filter and reads every vendor.
  • Records at the cursor boundary are read again. In testing, updated_after and created_after include records exactly at the given time. Ramp returns vendor updated_at values rounded down to whole seconds, so from_updated_at also returns the vendor at the saved cursor. The next sync re-emits records whose cursor value equals the saved cursor. Use the Incremental - Append + Deduped sync mode to keep one row per id.
  • receipts only picks up new receipts. Ramp's receipts have no updated_at field, so incremental syncs use created_at. Changes to a receipt after the sync that first read it aren't synced until you refresh the stream.
  • Incremental vendors leaves spend totals stale. The total_spend_last_30_days, total_spend_last_365_days, total_spend_ytd, and total_spend_all_time fields are running totals that change as days pass. Ramp doesn't document that those changes move the vendor's updated_at. An incremental sync only re-reads vendors whose updated_at moved, so these totals can keep the value from the last sync that read the vendor. If you report on them, sync vendors with a Full Refresh mode instead.
  • Incremental vendors keeps deleted vendors. A vendor deleted in Ramp stops appearing in the API, so an incremental sync never sees the deletion and the destination keeps its last row. Full Refresh - Overwrite removes it on the next sync.

Supported Streams​

All endpoints are under /developer/v1.

StreamAPI endpointRequired scopePrimary keySync modesIncremental cursor
cardsGET /cardscards:readidFull refreshNone
transactionsGET /transactionstransactions:readidFull refresh, incrementalupdated_at
reimbursementsGET /reimbursementsreimbursements:readidFull refresh, incrementalupdated_at
usersGET /usersusers:readidFull refreshNone
departmentsGET /departmentsdepartments:readidFull refreshNone
locationsGET /locationslocations:readidFull refreshNone
entitiesGET /entitiesentities:readidFull refreshNone
businessGET /businessbusiness:readidFull refreshNone
business_balanceGET /business/balancebusiness:readNoneFull refreshNone
fundsGET /fundsfunds:readidFull refreshNone
spend_programsGET /spend-programsspend_programs:readidFull refreshNone
billsGET /billsbills:readidFull refreshNone
vendorsGET /vendorsvendors:readidFull refresh, incrementalupdated_at
vendor_contactsGET /vendors/{vendor_id}/contactsvendors:readvendor_id, idFull refreshNone
vendor_agreementsPOST /vendors/agreementsvendors:readidFull refreshNone
receiptsGET /receiptsreceipts:readidFull refresh, incrementalcreated_at
merchantsGET /merchantsmerchants:readidFull refreshNone
purchase_ordersGET /purchase-orderspurchase_orders:readidFull refreshNone

Card spend​

cards returns physical and virtual cards, including their state, cardholder, card program, and spending restrictions. It doesn't return terminated cards, because it reads Ramp's legacy cards endpoint (GET /cards), which leaves them out. With the Overwrite or Overwrite + Deduped sync mode, a card disappears from the destination on the first sync after it's terminated. Its transactions stay in the transactions stream, so use a left join from transactions.card_id to cards, or read the cardholder from transactions.card_holder. With Append, the destination keeps every earlier copy of the card, and the newest copy still shows the state it had before termination, such as ACTIVE.

transactions returns card transactions in every state, including DECLINED. Declined transactions have state: DECLINED and a populated decline_details object, so filter them out if you calculate spend totals.

The connector also requests the purchase data merchants send to Ramp, and stores it in the merchant_data field. It can include itemized receipt lines, a merchant reference, and flight, lodging, or car rental details. merchant_data is null for transactions whose merchant sent no purchase data. Versions before 0.3.0 didn't request this data, so to fill in merchant_data for transactions you've already synced, refresh the transactions stream.

reimbursements returns out-of-pocket reimbursements and repayments. Ramp's endpoint returns one direction at a time, so the connector requests both BUSINESS_TO_USER (out-of-pocket reimbursements) and USER_TO_BUSINESS (repayments) and emits them into one stream. Use the direction field to tell them apart.

Organization and spend controls​

users returns users in every status. Ramp's users list leaves out suspended users by default, so the connector reads suspended users in a second request.

business returns one record with your business's details. business_balance returns one snapshot of your current balances on each sync. It has no primary key, so with Append each sync adds a new row.

funds includes terminated funds. The connector reads active and terminated funds in separate requests.

Accounts payable and procurement​

bills includes archived (deleted) bills. The connector reads active and archived bills in separate requests.

vendors doesn't include draft vendors or vendors still waiting for approval, because Ramp's vendors list leaves them out by default. The connector requests each vendor's ERP subsidiary identifiers. In incremental syncs, the spend total fields aren't kept current and deleted vendors aren't removed; see Supported sync modes.

vendor_contacts reads the contacts of every vendor on each sync, even when vendors syncs incrementally, and adds the vendor_id to every record. If Ramp returns 404 Not Found for a vendor, the connector skips that vendor.

vendor_agreements and purchase_orders include archived records.

receipts includes Ramp's OCR data for each receipt.

purchase_orders requires Ramp Plus. If your Ramp plan doesn't include purchase orders, deselect this stream.

IP allow list​

If you use Airbyte Cloud and your organization restricts access to specific IPs, add the Airbyte Cloud IP addresses to your allow list.

Performance considerations​

Ramp allows 200 requests per rolling 10-second window per source IP address, and returns 429 Too Many Requests when you exceed it. The connector limits itself to 180 requests per 10 seconds and retries failed requests up to 5 times with exponential backoff. Other Ramp sources or integrations that run from the same IP address share Ramp's limit, so they can still trigger 429 responses.

The connector reads 50 records per page. vendor_contacts makes at least one request per vendor, so its request count grows with the number of vendors. Ramp terminates requests that take longer than 60 seconds with a 504 Gateway Timeout. See Ramp's rate limits and timeouts guide.

Ramp's client credentials access tokens last 10 days. The connector requests a token for each stream it reads and reuses that token for the stream's requests.

Limitations & Troubleshooting​

Limitations​

  • Declined transactions from before version 0.1.0 aren't backfilled automatically. Versions before 0.1.0 didn't sync declined transactions. To pull in declined transactions older than your current cursor, refresh the transactions stream.
  • Date and timestamp fields are typed. The connector declares Ramp's ISO 8601 date and timestamp fields with date or date-time formats, so typed destinations store them as dates and timestamps instead of text. The streams added in version 0.2.0 were typed from the start; cards, transactions, and reimbursements were typed in version 1.0.0. Three date-like fields stay strings because Ramp doesn't return them in ISO 8601 format: cards.expiration (MMYY, for example 0430), and business_balance.next_billing_date and prev_billing_date (MM/DD/YYYY). If you're upgrading from a version before 1.0.0, follow the migration guide.
  • One business per source. Client credentials are issued to a single Ramp business. To sync several businesses, create one Airbyte source per business.

Deletions​

Ramp's API doesn't report hard deletes. Where Ramp's list endpoints leave archived or terminated records out by default, the connector requests them too, so a deleted record keeps arriving with its final state:

  • bills: archived bills have archived_at set.
  • purchase_orders: archived purchase orders have archived_at set.
  • vendor_agreements: archived agreements have deleted_at set.
  • funds: terminated funds have state: TERMINATED.
  • users: deactivated and suspended users stay in the stream with status USER_INACTIVE or USER_SUSPENDED.

Filter on these fields downstream if you only want live records. cards is the exception: the legacy cards endpoint the connector reads doesn't return terminated cards. See Card spend for how they leave the destination.

Configuration errors​

The connector reports these Ramp errors as configuration errors, so Airbyte doesn't retry them:

ErrorCauseFix
Ramp rejected the client ID or client secretThe token request returned 400 or 401.Copy the client ID and client secret again from Company > Developer > your app, and confirm the app has the Client Credentials grant type.
Your Ramp app is not allowed to read this dataRamp returned error code DEVELOPER_7100. The connector requests every stream's scope when it gets a token. Ramp doesn't fail the token request when the app lacks one of those scopes. It issues a token without that scope, and only the streams that need it fail.Enable the missing read scope on your app, then test the source again. Or deselect the streams that need it.
Ramp no longer accepts this connector's access tokenRamp returned error code DEVELOPER_7002.Check that the Ramp app still exists and that its client secret hasn't been rotated, then test the source again.
Ramp rejected the connector's credentialsAny other 401 response.Re-enter the client ID and client secret.
Ramp denied access to this dataAny other 403 response.Confirm the app has the scope named in the error. For purchase_orders, confirm your plan includes Ramp Plus.

Reference​

Config fields reference

Field
Type
Property name
string
client_id
string
client_secret
string
api_url
string
start_date

Changelog​

Expand to review
VersionDatePull RequestSubject
1.1.02026-10-1588938Make vendors incremental on updated_at, declare the vendors.updated_at field, show a readable Start Date format hint, and hide the generic Airbyte setup steps from the in-app guide
1.0.22026-10-1488895Replace the outdated README with the shared declarative-source README, and rebuild the icon from Ramp's press-kit glyph
1.0.12026-10-1388768Update dependencies
1.0.02026-10-1288373Declare 13 date and timestamp fields on cards, transactions and reimbursements with their real types. See the migration guide
0.3.02026-10-0888365Request merchant purchase data on transactions and declare 10 more fields Ramp already returns
0.2.12026-10-0687999Update dependencies
0.2.02026-10-0287610Add 15 streams for Ramp's organisation, spend-control, accounts-payable and procurement resources
0.1.02026-10-0186957Map Ramp auth and scope errors to config errors, add a rate-limit budget, filter transactions server-side, sync declined transactions, declare missing fields, and make start_date optional
0.0.82026-09-2987331Update dependencies
0.0.72026-09-2286778Update dependencies
0.0.62026-09-1586193Update dependencies
0.0.52026-09-0885624Update dependencies
0.0.42026-08-2084843Add hidden configurable API base URL for sandbox testing
0.0.32026-08-1884721Update dependencies
0.0.22026-08-1184077Update dependencies
0.0.12026-08-0683706Initial release by @MercureTony via Connector Builder