providers/claude/plugin/skills/apideck-migration/SKILL.md
Guide for migrating from direct third-party API integrations to Apideck's unified API. Use when a user wants to replace their existing Salesforce, HubSpot, QuickBooks, Xero, or other direct API integrations with Apideck, or when consolidating multiple integrations into a single unified layer.
npx skillsauth add apideck-libraries/api-skills apideck-migrationInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
This skill helps migrate existing direct third-party API integrations (Salesforce, HubSpot, QuickBooks, Xero, etc.) to Apideck's unified API layer. The benefit is replacing N separate integrations with a single Apideck integration that supports 200+ connectors.
pass_through for connector-specific fields that don't map to the unified model.pass_through or Proxy APIReplace read operations first since they're non-destructive:
// BEFORE: Direct Salesforce API
const contacts = await salesforce.sobjects.Contact.find({
Email: "[email protected]",
});
// AFTER: Apideck Unified API
const { data } = await apideck.crm.contacts.list({
serviceId: "salesforce",
filter: { email: "[email protected]" },
});
Replace create/update/delete operations:
// BEFORE: Direct HubSpot API
const contact = await hubspot.crm.contacts.basicApi.create({
properties: {
firstname: "John",
lastname: "Doe",
email: "[email protected]",
company: "Acme Corp",
},
});
// AFTER: Apideck Unified API
const { data } = await apideck.crm.contacts.create({
serviceId: "hubspot",
contact: {
first_name: "John",
last_name: "Doe",
emails: [{ email: "[email protected]", type: "primary" }],
company_name: "Acme Corp",
},
});
Replace direct webhook handlers with Apideck's unified webhooks:
// BEFORE: Salesforce-specific webhook handler
app.post("/webhooks/salesforce", (req, res) => {
const event = req.body;
if (event.type === "ContactChangeEvent") {
handleContactChange(event);
}
});
// AFTER: Apideck unified webhook handler
app.post("/webhooks/apideck", (req, res) => {
const signature = req.headers["x-apideck-signature"];
if (!verifySignature(req.body, signature, secret)) {
return res.status(401).send("Invalid signature");
}
const { event_type, entity_id, service_id } = req.body.payload;
// Works for ALL connectors, not just Salesforce
if (event_type === "crm.contact.updated") {
handleContactChange(entity_id, service_id);
}
res.status(200).send("OK");
});
| Salesforce API | Apideck Unified API |
|---------------|---------------------|
| sobjects.Contact.create() | crm.contacts.create({ serviceId: "salesforce" }) |
| sobjects.Account.find() | crm.companies.list({ serviceId: "salesforce" }) |
| sobjects.Opportunity.update() | crm.opportunities.update({ serviceId: "salesforce" }) |
| sobjects.Lead.create() | crm.leads.create({ serviceId: "salesforce" }) |
| sobjects.Task.create() | crm.activities.create({ serviceId: "salesforce" }) |
| Custom fields via custom_sf_field__c | pass_through: [{ service_id: "salesforce", extend_object: { custom_sf_field__c: "value" } }] |
| HubSpot API | Apideck Unified API |
|-------------|---------------------|
| crm.contacts.basicApi.create() | crm.contacts.create({ serviceId: "hubspot" }) |
| crm.companies.basicApi.getAll() | crm.companies.list({ serviceId: "hubspot" }) |
| crm.deals.basicApi.create() | crm.opportunities.create({ serviceId: "hubspot" }) |
| crm.contacts.searchApi.doSearch() | crm.contacts.list({ serviceId: "hubspot", filter: { ... } }) |
| QuickBooks API | Apideck Unified API |
|---------------|---------------------|
| Invoice.create() | accounting.invoices.create({ serviceId: "quickbooks" }) |
| Customer.findAll() | accounting.customers.list({ serviceId: "quickbooks" }) |
| Bill.create() | accounting.bills.create({ serviceId: "quickbooks" }) |
| Payment.create() | accounting.payments.create({ serviceId: "quickbooks" }) |
| JournalEntry.create() | accounting.journalEntries.create({ serviceId: "quickbooks" }) |
| CompanyInfo.get() | accounting.companyInfo.get({ serviceId: "quickbooks" }) |
| Xero API | Apideck Unified API |
|----------|---------------------|
| xero.accountingApi.createInvoices() | accounting.invoices.create({ serviceId: "xero" }) |
| xero.accountingApi.getContacts() | accounting.customers.list({ serviceId: "xero" }) |
| xero.accountingApi.createBankTransactions() | accounting.payments.create({ serviceId: "xero" }) |
| xero.accountingApi.getReportBalanceSheet() | accounting.balanceSheet.get({ serviceId: "xero" }) |
| BambooHR API | Apideck Unified API |
|-------------|---------------------|
| GET /employees/directory | hris.employees.list({ serviceId: "bamboohr" }) |
| POST /employees | hris.employees.create({ serviceId: "bamboohr" }) |
| GET /employees/{id} | hris.employees.get({ serviceId: "bamboohr", id }) |
| PUT /employees/{id}/time_off/request | hris.timeOffRequests.create({ serviceId: "bamboohr" }) |
| Google Drive API | Apideck Unified API |
|-----------------|---------------------|
| drive.files.list() | fileStorage.files.list({ serviceId: "google-drive" }) |
| drive.files.create() | fileStorage.files.create({ serviceId: "google-drive" }) |
| drive.files.get() | fileStorage.files.get({ serviceId: "google-drive" }) |
| drive.files.export() | fileStorage.files.download({ serviceId: "google-drive" }) |
| drive.permissions.create() | fileStorage.sharedLinks.create({ serviceId: "google-drive" }) |
For one-off connector-specific fields in request bodies:
const { data } = await apideck.crm.contacts.create({
serviceId: "salesforce",
contact: {
first_name: "John",
last_name: "Doe",
pass_through: [
{
service_id: "salesforce",
operation_id: "contactsAdd",
extend_object: {
RecordTypeId: "012000000000001",
Custom_Score__c: 85,
},
},
],
},
});
For fields that are used repeatedly, configure custom mapping in Vault so they appear as part of the unified model:
// Set up custom mapping via Vault API
await apideck.vault.customMappings.update({
unifiedApi: "crm",
serviceId: "salesforce",
id: "mapping_123",
customMapping: {
value: "$.Custom_Score__c",
},
});
// Now the field appears in custom_fields on every response
const { data } = await apideck.crm.contacts.get({
id: "contact_123",
serviceId: "salesforce",
});
// data.custom_fields includes { id: "mapping_123", value: 85 }
For operations not supported by the unified API, use the Proxy to make direct downstream calls while still using Apideck's managed authentication:
const response = await fetch("https://unify.apideck.com/proxy", {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"x-apideck-app-id": appId,
"x-apideck-consumer-id": consumerId,
"x-apideck-service-id": "salesforce",
"x-apideck-downstream-url": "/services/data/v59.0/sobjects/CustomObject__c",
"x-apideck-downstream-method": "GET",
"Content-Type": "application/json",
},
});
raw=true to Apideck calls to compare with the original API responseOnce migrated to Apideck:
development
Jira Teams via Apideck's Proxy API + managed Vault auth — Apideck handles auth and proxies HTTP calls to Jira Teams's native API. Use when the user wants to call Jira Teams (no unified API resource mapping). Routes through Apideck with serviceId "jira-teams".
development
Jira Service Desk via Apideck's Proxy API + managed Vault auth — Apideck handles auth and proxies HTTP calls to Jira Service Desk's native API. Use when the user wants to call Jira Service Desk (no unified API resource mapping). Routes through Apideck with serviceId "jira-service-desk".
development
Jira Data Center via Apideck's Proxy API + managed Vault auth — Apideck handles auth and proxies HTTP calls to Jira Data Center's native API. Use when the user wants to call Jira Data Center (no unified API resource mapping). Routes through Apideck with serviceId "jira-data-center".
development
JetBrains YouTrack via Apideck's Proxy API + managed Vault auth — Apideck handles auth and proxies HTTP calls to JetBrains YouTrack's native API. Use when the user wants to call JetBrains YouTrack (no unified API resource mapping). Routes through Apideck with serviceId "jetbrains-youtrack".