Summary and recommendation
Ramp's REST API lives at `https://api.ramp.com/developer/v1` and uses OAuth 2.0 with two flows: `client_credentials` for server-to-server integrations and `authorization_code` for user-delegated access.
Scopes are granted at app creation time and are additive - request only what the integration needs (`users:read`, `users:write`, `users:deactivate`, `departments:read`, `locations:read` cover the full user lifecycle).
The SCIM 2.0 endpoint (`https://api.ramp.com/scim/v2`) uses a separate long-lived bearer token, not an OAuth token; do not mix the two across integrations.
This API surface fits naturally into an identity graph where Ramp user records - carrying `employee_id`, `manager_id`, `department_id`, and `location_id` - can be joined against HR and IdP sources to maintain a consistent, auditable view of who has spend access and at what scope.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (client credentials flow for server-to-server; authorization code flow for user-delegated access) |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Free (included on all plans) |
Authentication
Auth method: OAuth 2.0 (client credentials flow for server-to-server; authorization code flow for user-delegated access)
Setup steps
- Log in to Ramp and navigate to Settings > Developer > API.
- Create an OAuth application to obtain a client_id and client_secret.
- Request an access token via POST to https://api.ramp.com/developer/v1/token using client_credentials grant type.
- Include the returned Bearer token in the Authorization header for all API requests.
- Select required scopes during app creation; tokens are scoped to the permissions granted.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| users:read | Read user profiles and list users. | GET /users, GET /users/{id} |
| users:write | Create and update user records. | POST /users, PATCH /users/{id} |
| users:deactivate | Deactivate (offboard) a user. | POST /users/{id}/deactivate |
| departments:read | Read department data referenced in user objects. | GET /departments |
| locations:read | Read location data referenced in user objects. | GET /locations |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string (UUID) | Unique Ramp user identifier. | system-generated | immutable | Used as path parameter in all user-specific endpoints. |
| first_name | string | User's first name. | required | optional | |
| last_name | string | User's last name. | required | optional | |
| string | Primary email address; used for login. | required | optional | Must be unique within the organization. | |
| phone | string | User's phone number. | optional | optional | |
| role | enum | User role within Ramp (e.g., BUSINESS_OWNER, ADMIN, CARDHOLDER, BOOKKEEPER). | required | optional | Determines permissions within the platform. |
| department_id | string (UUID) | Reference to the user's department. | optional | optional | Must be a valid department UUID from GET /departments. |
| location_id | string (UUID) | Reference to the user's location. | optional | optional | Must be a valid location UUID from GET /locations. |
| manager_id | string (UUID) | UUID of the user's manager. | optional | optional | Used for approval workflows. |
| status | enum | Account status: ACTIVE or INACTIVE. | system-set (ACTIVE) | via deactivate endpoint | Cannot be set directly via PATCH; use the deactivate endpoint. |
| direct_manager_id | string (UUID) | Direct manager reference for spend approval chains. | optional | optional | |
| employee_id | string | External HR system employee identifier. | optional | optional | Useful for HRIS sync reconciliation. |
Core endpoints
List users
- Method: GET
- URL:
https://api.ramp.com/developer/v1/users - Watch out for: Pagination uses a cursor token in page.next; pass as ?next= on subsequent requests.
Request example
GET /developer/v1/users?page_size=100
Authorization: Bearer {token}
Response example
{
"data": [{"id":"uuid","email":"user@co.com","first_name":"Jane","status":"ACTIVE"}],
"page": {"next": "cursor_token"}
}
Get user by ID
- Method: GET
- URL:
https://api.ramp.com/developer/v1/users/{id} - Watch out for: Returns 404 if user is deactivated and not found; deactivated users may still be retrievable depending on API version.
Request example
GET /developer/v1/users/user-uuid
Authorization: Bearer {token}
Response example
{
"id": "user-uuid",
"email": "user@co.com",
"role": "CARDHOLDER",
"status": "ACTIVE"
}
Create user (invite)
- Method: POST
- URL:
https://api.ramp.com/developer/v1/users/deferred - Watch out for: Ramp uses a deferred user creation model; the user receives an invite email and must accept before becoming fully ACTIVE.
Request example
POST /developer/v1/users/deferred
{
"first_name": "Jane",
"last_name": "Doe",
"email": "jane@co.com",
"role": "CARDHOLDER",
"department_id": "dept-uuid"
}
Response example
{
"id": "new-user-uuid",
"email": "jane@co.com",
"status": "INVITE_PENDING"
}
Update user
- Method: PATCH
- URL:
https://api.ramp.com/developer/v1/users/{id} - Watch out for: Cannot change user status via PATCH; use the dedicated deactivate endpoint.
Request example
PATCH /developer/v1/users/user-uuid
{
"department_id": "new-dept-uuid",
"manager_id": "mgr-uuid"
}
Response example
{
"id": "user-uuid",
"department_id": "new-dept-uuid",
"manager_id": "mgr-uuid"
}
Deactivate user
- Method: POST
- URL:
https://api.ramp.com/developer/v1/users/{id}/deactivate - Watch out for: Deactivation cancels associated cards. Ensure card offboarding is handled before or after this call.
Request example
POST /developer/v1/users/user-uuid/deactivate
Authorization: Bearer {token}
Response example
{
"id": "user-uuid",
"status": "INACTIVE"
}
List departments
- Method: GET
- URL:
https://api.ramp.com/developer/v1/departments - Watch out for: Department IDs are required when assigning users to departments; fetch this list before user creation.
Request example
GET /developer/v1/departments
Authorization: Bearer {token}
Response example
{
"data": [{"id":"dept-uuid","name":"Engineering"}]
}
List locations
- Method: GET
- URL:
https://api.ramp.com/developer/v1/locations - Watch out for: Location IDs must be pre-fetched; invalid IDs on user create/update return a 400 error.
Request example
GET /developer/v1/locations
Authorization: Bearer {token}
Response example
{
"data": [{"id":"loc-uuid","name":"New York HQ"}]
}
Get current user (token introspection)
- Method: GET
- URL:
https://api.ramp.com/developer/v1/users/me - Watch out for: Only valid for authorization_code flow tokens; client_credentials tokens are not user-bound.
Request example
GET /developer/v1/users/me
Authorization: Bearer {token}
Response example
{
"id": "uuid",
"email": "admin@co.com",
"role": "ADMIN"
}
Rate limits, pagination, and events
- Rate limits: Ramp enforces rate limits on API requests. Official docs note a limit of 100 requests per minute per client.
- Rate-limit headers: Unknown
- Retry-After header: Unknown
- Rate-limit notes: Official docs specify 100 req/min. Behavior of rate-limit response headers and Retry-After is not explicitly documented; treat as unknown.
- Pagination method: cursor
- Default page size: 100
- Max page size: 100
- Pagination pointer: next
| Plan | Limit | Concurrent |
|---|---|---|
| All plans | 100 requests per minute | 0 |
- Webhooks available: Yes
- Webhook notes: Ramp supports webhooks for real-time event notifications. Webhooks are configured in the Developer settings and deliver POST payloads to a registered HTTPS endpoint.
- Alternative event strategy: Poll GET /users with updated_after filter parameter for environments where webhooks are not feasible.
- Webhook events: user.created, user.updated, user.deactivated, card.activated, card.suspended, transaction.created, reimbursement.created
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Free (included on all plans)
Endpoint: https://api.ramp.com/scim/v2
Supported operations: GET /Users, GET /Users/{id}, POST /Users, PUT /Users/{id}, PATCH /Users/{id}, DELETE /Users/{id}, GET /Groups, POST /Groups, PATCH /Groups/{id}, DELETE /Groups/{id}
Limitations:
- SCIM token is generated from Ramp Settings > Team > SCIM; it is a long-lived bearer token, not an OAuth token.
- Full SCIM provisioning tested and documented for Okta, Azure AD (Entra ID), Rippling, and OneLogin.
- Google Workspace SCIM is not officially supported; Google SSO is available but not SCIM provisioning.
- Group push maps to Ramp departments; department must exist in Ramp or be created via SCIM group push.
- SCIM DELETE deactivates the user; it does not permanently delete the Ramp account or historical spend data.
Common scenarios
Onboarding via REST requires pre-fetching department and location UUIDs before POST /users/deferred. The endpoint is invite-based: the user lands in INVITE_PENDING status and cannot be issued a card until they accept the invite and transition to ACTIVE.
Poll GET /users/{id} to detect the transition; there is no synchronous confirmation.
Offboarding via POST /users/{id}/deactivate is a single call that simultaneously sets status to INACTIVE and cancels all associated virtual and physical cards. This is not reversible via the API - reactivation requires manual action in the Ramp admin UI.
Build card offboarding coordination into your workflow before or immediately after this call.
For Okta SCIM sync, configure the base URL as https://api.ramp.com/scim/v2 with the Ramp-generated SCIM bearer token.
Okta group push maps to Ramp Departments, not Roles - role assignment defaults to CARDHOLDER and must be corrected manually or via a follow-up PATCH /users/{id} call through the REST API.
Onboard a new employee via REST API
- Obtain OAuth 2.0 client_credentials token with users:write, departments:read, locations:read scopes.
- GET /departments and GET /locations to retrieve valid UUIDs for the employee's department and location.
- POST /users/deferred with first_name, last_name, email, role, department_id, location_id, manager_id.
- User receives invite email; poll GET /users/{id} until status transitions from INVITE_PENDING to ACTIVE.
- Optionally issue a card via POST /cards once user is ACTIVE.
Watch out for: If the invite email is not accepted, the user remains INVITE_PENDING and cannot be issued a card. Resend invite from Ramp UI or via API if supported.
Offboard an employee and suspend cards
- Obtain token with users:deactivate scope.
- POST /users/{id}/deactivate - this simultaneously deactivates the user and suspends all associated cards.
- Verify status is INACTIVE via GET /users/{id}.
- Reassign any open reimbursements or pending transactions to another user via the Ramp UI or API.
Watch out for: Deactivation is not reversible via the API; reactivation must be done manually in the Ramp admin UI.
Sync users from Okta via SCIM
- In Ramp Settings > Team, enable SCIM and copy the generated SCIM bearer token.
- In Okta, add the Ramp application from the Okta Integration Network (OIN).
- Configure SCIM base URL as https://api.ramp.com/scim/v2 and paste the bearer token.
- Enable provisioning features: Create Users, Update User Attributes, Deactivate Users, Push Groups.
- Assign users and groups in Okta; Okta pushes SCIM POST /Users and PATCH /Groups to Ramp.
- Verify users appear in Ramp with correct department (mapped from Okta group) and role.
Watch out for: Okta group push creates Ramp Departments, not Roles. Role assignment defaults to CARDHOLDER; admin roles must be set manually in Ramp after provisioning.
Why building this yourself is a trap
The deferred creation model is the most common integration trap: callers assume a 201 from POST /users/deferred means the user is ready, but INVITE_PENDING blocks card issuance and any downstream workflow that depends on an ACTIVE user. Build explicit status polling with a timeout and alerting for stuck invites.
Rate limits are set at 100 requests per minute across all plans. Rate-limit response headers and Retry-After behavior are not documented - treat them as unknown and implement exponential backoff unconditionally for bulk operations. Cursor-based pagination uses page.next; offset pagination is not supported, so any integration that assumes offset behavior will silently drop records.
SCIM DELETE deactivates the user and cancels cards but does not remove historical spend data - this is correct behavior for audit retention but should be communicated to finance stakeholders who may expect a clean removal.
Finally, GET /users/me is only valid for authorization_code tokens; calling it with a client_credentials token will not return a user context.
Automate Ramp workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.