ReferenceReference by module

Integrations API

Every Integrations action (22) and data model (8): endpoints, scopes, input, preconditions, events and examples.

Marketplaces, online shops, carriers, e-invoice and Google reviews, synced into your own orders, products, stock and customers.

Module code integrations · 22 actions · 8 data models · 22 events. A key or token never does more here than the person behind it can; row-level security applies exactly as in the app. Scopes: integrations (everything), integrations:read (read only) or integrations:<capability>.

Resources

ResourceTableList and readPOSTPATCHDELETE
carrier_shipmentscarrier_shipment/api/v1/carrier_shipments
channel_listingschannel_listing/api/v1/channel_listings
einvoice_documentseinvoice_document/api/v1/einvoice_documents
integration_accountsintegration_account/api/v1/integration_accounts
integration_inboundsintegration_inbound/api/v1/integration_inbounds
integration_issuesintegration_issue/api/v1/integration_issues
integration_reviewsintegration_review/api/v1/integration_reviews
integration_runsintegration_run/api/v1/integration_runs

Lists take limit (up to 200), cursor, order (e.g. -created_at), fields and q; every other query parameter is a column filter: ?status=paid, ?total[gte]=100, ?id[in]=a,b, ?x=null.

Actions

ActionNeedsWhat it does
integrations.cancel_shipmentintegrations:writeCancel a parcel
integrations.connectintegrations:manageConnect an app for syncing
integrations.create_shipmentintegrations:writeSend with a carrier
integrations.disconnectintegrations:deleteDisconnect an app
integrations.issue_einvoiceintegrations:writeInvoice an order (e-Arşiv / e-Fatura)
integrations.map_listingintegrations:writeTie a listing to a product
integrations.publish_listingsintegrations:writePublish product variants to a marketplace
integrations.raise_issueintegrations:handleRaise a sync issue
integrations.record_einvoiceintegrations:handleRecord an e-invoice answer
integrations.record_inboundintegrations:handleRecord a webhook delivery
integrations.record_review_replyintegrations:handleRecord a review reply answer
integrations.record_reviewsintegrations:handleRecord reviews
integrations.record_runintegrations:handleRecord a sync run
integrations.record_shipmentintegrations:handleRecord a carrier answer
integrations.record_stock_pushintegrations:handleRecord a stock push
integrations.record_testintegrations:manageRecord a connection test
integrations.reply_reviewintegrations:writeReply to a review
integrations.request_syncintegrations:writeSync now
integrations.resolve_issueintegrations:writeClose a sync issue
integrations.set_pausedintegrations:managePause or resume syncing
integrations.update_settingsintegrations:manageChange what an app syncs
integrations.upsert_listingsintegrations:handleRecord listings

integrations.cancel_shipment

Cancel a parcel — Cancels a parcel the carrier has not picked up yet; the carrier is told in the background.

Needs integrations:write · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/carrier_shipments/{id}/actions/cancel_shipment
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.cancel_shipment

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Parcel · id of carrier_shipment

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe parcel must exist.
not_cancellableOnly before pick-up.

Events it publishes: integrations.shipment_updated

What it writes: carrier_shipment (update) — Marks it cancelled

curl -X POST https://app.getera.io/api/v1/carrier_shipments/CARRIER_SHIPMENT_ID/actions/cancel_shipment \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.shipment_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.carrierShipments.cancelShipment("CARRIER_SHIPMENT_ID")
era carrier_shipments cancel_shipment CARRIER_SHIPMENT_ID
tools/call
{
  "name": "era__integrations__cancel_shipment",
  "arguments": {
    "id": "CARRIER_SHIPMENT_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_cancellable · 429 slow down

integrations.connect

Connect an app for syncing — Links a connection (its sealed key) to what Era syncs it with: a sales channel and warehouse for a marketplace or shop.

Needs integrations:manage · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/integration_accounts/actions/connect
API key or OAuth token · integrations:manage
  • Canonical address: POST /api/v1/actions/integrations.connect

Input

FieldTypeRequiredNotes
providerstringyesApp · max 41
labelstringName · max 160
credentialIduuidConnection · id of credential
channelIduuidSales channel · id of channel
warehouseIduuidWarehouse · id of warehouse
configobject / arrayAccount settings
settingsobject / arrayWhat to sync

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
unknown_providerThe app must be one Era integrates.
credential_not_foundThe connection must exist in this workspace.
provider_mismatchThe connection must be for the same app.
credential_takenOne connection feeds one integration account.
channel_requiredA marketplace or shop needs an existing sales channel.
channel_takenOne sales channel is fed by one account.
bad_configThe warehouse must exist and the settings stay small.
bad_settingOnly known sync settings, with sensible values.

Events it publishes: integrations.connected

What it writes: integration_account (insert) — The account, with a fresh inbound-webhook token

curl -X POST https://app.getera.io/api/v1/integration_accounts/actions/connect \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"provider":"App"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.connected"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.connect({
  provider: "App"
})
era integration_accounts connect \
  --provider "App"
tools/call
{
  "name": "era__integrations__connect",
  "arguments": {
    "provider": "App"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 unknown_provider, credential_not_found, provider_mismatch, credential_taken, channel_required, channel_taken, bad_config, bad_setting · 429 slow down

integrations.create_shipment

Send with a carrier — Books a parcel for an order with a connected carrier (Yurtiçi, Aras, MNG, Sürat, HepsiJet); tracking follows by itself.

Needs integrations:write · changes data

POSThttps://app.getera.io/api/v1/carrier_shipments/actions/create_shipment
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.create_shipment

Input

FieldTypeRequiredNotes
orderIduuidyesOrder · id of sales_order
accountIduuidCarrier account · Empty: the first connected carrier. · id of integration_account
piecesnumberParcels · min 1 · max 99
desinumberDesi · min 0 · max 1000
weightKgnumberWeight (kg) · min 0 · max 1000
codAmountnumber (money)Cash on delivery (minor units) · min 0

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
order_not_foundThe order must exist.
no_shipping_accountA carrier must be connected and active.
not_shipping_accountThe named account must be a carrier.
order_not_shippableA draft, cancelled, expired or returned order does not ship.
shipment_existsOne open parcel per order and carrier.
no_addressThe order needs a delivery address with a street and a city.

Events it publishes: integrations.shipment_requested

What it writes: carrier_shipment (insert) — The parcel request; the worker books it at the carrier

curl -X POST https://app.getera.io/api/v1/carrier_shipments/actions/create_shipment \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"orderId":"SALES_ORDER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.shipment_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.carrierShipments.createShipment({
  orderId: "SALES_ORDER_ID"
})
era carrier_shipments create_shipment \
  --order-id "SALES_ORDER_ID"
tools/call
{
  "name": "era__integrations__create_shipment",
  "arguments": {
    "orderId": "SALES_ORDER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 order_not_found, no_shipping_account, not_shipping_account, order_not_shippable, shipment_exists, no_address · 429 slow down

integrations.disconnect

Disconnect an app — Stops syncing for good. Orders, products and history stay; the key is removed with the connection itself (apps.disconnect).

Needs integrations:delete · removes or cannot be undone · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/disconnect
API key or OAuth token · integrations:delete
  • Canonical address: POST /api/v1/actions/integrations.disconnect

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Account · id of integration_account

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
already_disconnectedIt is disconnected once.

Events it publishes: integrations.disconnected

What it writes: integration_account (update) — Marks it disconnected; drops the webhook token

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/disconnect \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.disconnected"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.disconnect("INTEGRATION_ACCOUNT_ID")
era integration_accounts disconnect INTEGRATION_ACCOUNT_ID
tools/call
{
  "name": "era__integrations__disconnect",
  "arguments": {
    "id": "INTEGRATION_ACCOUNT_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:delete · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, already_disconnected · 429 slow down

integrations.issue_einvoice

Invoice an order (e-Arşiv / e-Fatura) — Asks the connected e-invoice provider (Paraşüt, Uyumsoft or Logo eLogo) to invoice an order: e-Fatura for a registered taxpayer, e-Arşiv otherwise.

Needs integrations:write · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/einvoice_documents/actions/issue_einvoice
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.issue_einvoice

Input

FieldTypeRequiredNotes
orderIduuidyesOrder · id of sales_order
accountIduuidE-invoice account · id of integration_account

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
order_not_foundThe order must exist.
no_einvoice_accountAn e-invoice provider must be connected and active.
not_einvoice_accountThe named account must be an e-invoice provider.
order_not_invoiceableA draft, cancelled or expired order is not invoiced.
already_invoicedOne live invoice per order and provider.

Events it publishes: integrations.einvoice_requested

What it writes: einvoice_document (insert) — The request; the worker sends it to the provider

curl -X POST https://app.getera.io/api/v1/einvoice_documents/actions/issue_einvoice \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"orderId":"SALES_ORDER_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.einvoice_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.einvoiceDocuments.issueEinvoice({
  orderId: "SALES_ORDER_ID"
})
era einvoice_documents issue_einvoice \
  --order-id "SALES_ORDER_ID"
tools/call
{
  "name": "era__integrations__issue_einvoice",
  "arguments": {
    "orderId": "SALES_ORDER_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 order_not_found, no_einvoice_account, not_einvoice_account, order_not_invoiceable, already_invoiced · 429 slow down

integrations.map_listing

Tie a listing to a product — Says which Era variant a marketplace listing is, so its orders take stock and Era’s stock reaches it.

Needs integrations:write · changes data

POSThttps://app.getera.io/api/v1/channel_listings/{id}/actions/map_listing
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.map_listing

Input

FieldTypeRequiredNotes
listingIduuidyesFilled from the path {id} · Listing · id of channel_listing
itemVariantIduuidVariant · Empty unties it. · id of item_variant
sourcestring (enum)How · Allowed values: manual, created

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe listing must exist.
variant_not_foundThe variant must exist.

Events it publishes: integrations.listing_mapped

What it writes: channel_listing (update) — Sets (or clears) the variant; the next push sends its stock

curl -X POST https://app.getera.io/api/v1/channel_listings/CHANNEL_LISTING_ID/actions/map_listing \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"itemVariantId":"ITEM_VARIANT_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.listing_mapped"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.channelListings.mapListing("CHANNEL_LISTING_ID", {
  itemVariantId: "ITEM_VARIANT_ID"
})
era channel_listings map_listing CHANNEL_LISTING_ID \
  --item-variant-id "ITEM_VARIANT_ID"
tools/call
{
  "name": "era__integrations__map_listing",
  "arguments": {
    "listingId": "CHANNEL_LISTING_ID",
    "itemVariantId": "ITEM_VARIANT_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, variant_not_found · 429 slow down

integrations.publish_listings

Publish product variants to a marketplace — After catalog.set_options and catalog.save_variant, publish the variants to Trendyol. Give each catalogue variant a SKU with catalog.save_variant, then supply variantId, barcode, images and Trendyol category/brand/attribute ids. The SKU keeps the approved listing mapped to the same Era variant. Prices come from the catalogue in minor units. Asynchronous: queued does not mean published; read integrations_status for the batch result.

Needs integrations:write · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/integration_runs/actions/publish_listings
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.publish_listings

Input

FieldTypeRequiredNotes
accountIduuidyesAccount · id of integration_account
modestring (enum)Operation · Allowed values: create, update_unapproved, update_content, update_variant
listingsobject / arrayyesVariants and marketplace fields · Array: variantId, barcode, quantity (defaults to free channel stock, never more than free stock), images (https URLs), meta: {brandId,categoryId,productMainId,vatRate,attributes}. All variants of one product share productMainId. listPrice is minor units. For approved content updates provide meta.contentId.

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
listing_account_unavailableAn active account supporting listing publication is required.
invalid_listing_request1–1000 unique variants with valid listing data must be visible in the catalogue.

Events it publishes: integrations.listing_publish_requested

What it writes: integration_run (insert) — Track the asynchronous publication request

curl -X POST https://app.getera.io/api/v1/integration_runs/actions/publish_listings \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"accountId":"INTEGRATION_ACCOUNT_ID","listings":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.listing_publish_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationRuns.publishListings({
  accountId: "INTEGRATION_ACCOUNT_ID",
  listings: {}
})
era integration_runs publish_listings --data '{"accountId":"INTEGRATION_ACCOUNT_ID","listings":{}}'
tools/call
{
  "name": "era__integrations__publish_listings",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "listings": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 listing_account_unavailable, invalid_listing_request · 429 slow down

integrations.raise_issue

Raise a sync issue — Something a person has to look at, in Turkish. The same thing again counts up instead of repeating.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_issues/actions/raise_issue
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.raise_issue

Input

FieldTypeRequiredNotes
accountIduuidyesAccount · id of integration_account
kindstringyesKind · max 40
externalRefstringAbout · max 300
messagestringyesMessage · max 2000
detailobject / arrayDetail
orderIduuidOrder · id of sales_order
itemVariantIduuidVariant · id of item_variant

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
bad_kindA known issue kind.

Events it publishes: integrations.issue_raised

What it writes: integration_issue (upsert) — One open issue per (account, kind, thing)

curl -X POST https://app.getera.io/api/v1/integration_issues/actions/raise_issue \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"accountId":"INTEGRATION_ACCOUNT_ID","kind":"Kind","message":"Message"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.issue_raised"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationIssues.raiseIssue({
  accountId: "INTEGRATION_ACCOUNT_ID",
  kind: "Kind",
  message: "Message"
})
era integration_issues raise_issue \
  --account-id "INTEGRATION_ACCOUNT_ID" \
  --kind "Kind" \
  --message "Message"
tools/call
{
  "name": "era__integrations__raise_issue",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "kind": "Kind",
    "message": "Message"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, bad_kind · 429 slow down

integrations.record_einvoice

Record an e-invoice answer — What the e-invoice provider did with the request.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/einvoice_documents/{id}/actions/record_einvoice
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_einvoice

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · E-invoice · id of einvoice_document
statusstringyesStatus · max 20
kindstringKind · max 20
externalIdstringProvider id · max 200
documentNumberstringNumber · max 100
pdfUrlstringPDF · max 1000
errorstringRefusal · max 1000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe e-invoice must exist.

Events it publishes: integrations.einvoice_updated

What it writes: einvoice_document (update) — The provider’s answer

curl -X POST https://app.getera.io/api/v1/einvoice_documents/EINVOICE_DOCUMENT_ID/actions/record_einvoice \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"status":"Status"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.einvoice_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.einvoiceDocuments.recordEinvoice("EINVOICE_DOCUMENT_ID", {
  status: "Status"
})
era einvoice_documents record_einvoice EINVOICE_DOCUMENT_ID \
  --status "Status"
tools/call
{
  "name": "era__integrations__record_einvoice",
  "arguments": {
    "id": "EINVOICE_DOCUMENT_ID",
    "status": "Status"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.record_inbound

Record a webhook delivery — Each delivery once; an accepted one nudges a sync (its body is never trusted as data).

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_inbounds/actions/record_inbound
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_inbound

Input

FieldTypeRequiredNotes
accountIduuidyesAccount · id of integration_account
externalIdstringyesDelivery · max 300
topicstringTopic · max 200
acceptedbooleanyesAccepted
reasonstringWhy refused · max 300

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.

Events it publishes: integrations.webhook_received

What it writes: integration_inbound (insert) — The delivery, deduped on its id

curl -X POST https://app.getera.io/api/v1/integration_inbounds/actions/record_inbound \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"accountId":"INTEGRATION_ACCOUNT_ID","externalId":"Delivery","accepted":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.webhook_received"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationInbounds.recordInbound({
  accountId: "INTEGRATION_ACCOUNT_ID",
  externalId: "Delivery",
  accepted: true
})
era integration_inbounds record_inbound \
  --account-id "INTEGRATION_ACCOUNT_ID" \
  --external-id "Delivery" \
  --accepted true
tools/call
{
  "name": "era__integrations__record_inbound",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "externalId": "Delivery",
    "accepted": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.record_review_reply

Record a review reply answer — Whether the review provider published the reply.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_reviews/{id}/actions/record_review_reply
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_review_reply

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Review · id of integration_review
okbooleanyesPublished
repliedAtstringWhen · max 40
errorstringRefusal · max 1000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe review must exist.

Events it publishes: integrations.review_replied

What it writes: integration_review (update) — The provider’s answer

curl -X POST https://app.getera.io/api/v1/integration_reviews/INTEGRATION_REVIEW_ID/actions/record_review_reply \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"ok":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.review_replied"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationReviews.recordReviewReply("INTEGRATION_REVIEW_ID", {
  ok: true
})
era integration_reviews record_review_reply INTEGRATION_REVIEW_ID \
  --ok true
tools/call
{
  "name": "era__integrations__record_review_reply",
  "arguments": {
    "id": "INTEGRATION_REVIEW_ID",
    "ok": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.record_reviews

Record reviews — The reviews a connected review provider holds now: new ones, edited ones, and replies made outside Era.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_reviews/actions/record_reviews
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_reviews

Input

FieldTypeRequiredNotes
accountIduuidyesAccount · id of integration_account
reviewsobject / arrayyesReviews

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
not_reviews_accountThe account must be a review provider (Google Business Profile).
invalid_reviewsThe reviews must be a list.

Events it publishes: integrations.reviews_synced

What it writes: integration_review (insert) — One row per review, updated in place on the next sync

curl -X POST https://app.getera.io/api/v1/integration_reviews/actions/record_reviews \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"accountId":"INTEGRATION_ACCOUNT_ID","reviews":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.reviews_synced"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationReviews.recordReviews({
  accountId: "INTEGRATION_ACCOUNT_ID",
  reviews: {}
})
era integration_reviews record_reviews --data '{"accountId":"INTEGRATION_ACCOUNT_ID","reviews":{}}'
tools/call
{
  "name": "era__integrations__record_reviews",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "reviews": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, not_reviews_account, invalid_reviews · 429 slow down

integrations.record_run

Record a sync run — Opens a run, or closes it with its counts and one Turkish sentence; moves the account’s cursors and health.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/record_run
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_run

Input

FieldTypeRequiredNotes
accountIduuidyesFilled from the path {id} · Account · id of integration_account
runIduuidRun
feedstringFeed · max 20
triggerstringTrigger · max 20
statusstring (enum)Status · Allowed values: running, ok, partial, failed, skipped
countsobject / arrayCounts
messagestringMessage · max 1000
jobIduuidJob
cursorsobject / arrayCursors
touchstringFeed done · max 20
errorstringError · max 2000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account (and the run, when named) must exist.

Events it publishes: integrations.run_finished

What it writes: integration_run (upsert) — The run row; integration_account (update) — Last sync times, cursors, health

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/record_run \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"runId":"RUN_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.run_finished"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.recordRun("INTEGRATION_ACCOUNT_ID", {
  runId: "RUN_ID"
})
era integration_accounts record_run INTEGRATION_ACCOUNT_ID \
  --run-id "RUN_ID"
tools/call
{
  "name": "era__integrations__record_run",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "runId": "RUN_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.record_shipment

Record a carrier answer — The carrier’s booking, tracking number, label or latest movement — or its refusal.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/carrier_shipments/{id}/actions/record_shipment
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_shipment

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Parcel · id of carrier_shipment
statusstringStatus · max 20
trackingNumberstringTracking number · max 100
barcodestringBarcode · max 100
labelUrlstringLabel · max 1000
trackingUrlstringTracking page · max 1000
lastEventstringLatest movement · max 500
lastEventAtstringWhen · max 40
errorstringRefusal · max 1000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe parcel must exist.

Events it publishes: integrations.shipment_updated

What it writes: carrier_shipment (update) — What the carrier said

curl -X POST https://app.getera.io/api/v1/carrier_shipments/CARRIER_SHIPMENT_ID/actions/record_shipment \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"status":"Status"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.shipment_updated"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.carrierShipments.recordShipment("CARRIER_SHIPMENT_ID", {
  status: "Status"
})
era carrier_shipments record_shipment CARRIER_SHIPMENT_ID \
  --status "Status"
tools/call
{
  "name": "era__integrations__record_shipment",
  "arguments": {
    "id": "CARRIER_SHIPMENT_ID",
    "status": "Status"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.record_stock_push

Record a stock push — What each listing was told and whether the channel took it.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/record_stock_push
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.record_stock_push

Input

FieldTypeRequiredNotes
accountIduuidyesFilled from the path {id} · Account · id of integration_account
resultsobject / arrayyesResults
batchRefstringProvider batch · max 200

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
malformed_resultsPush results are a list.

Events it publishes: integrations.stock_pushed

What it writes: channel_listing (update) — Last pushed quantity, or the refusal; integration_account (update) — Last push time

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/record_stock_push \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"results":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.stock_pushed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.recordStockPush("INTEGRATION_ACCOUNT_ID", {
  results: {}
})
era integration_accounts record_stock_push INTEGRATION_ACCOUNT_ID --data '{"results":{}}'
tools/call
{
  "name": "era__integrations__record_stock_push",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "results": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, malformed_results · 429 slow down

integrations.record_test

Record a connection test — Keeps the result of one harmless call to the provider on the account.

Needs integrations:manage · changes data

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/record_test
API key or OAuth token · integrations:manage
  • Canonical address: POST /api/v1/actions/integrations.record_test

Input

FieldTypeRequiredNotes
accountIduuidyesFilled from the path {id} · Account · id of integration_account
okbooleanyesPassed
messagestringyesWhat happened · max 1000

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.

Events it publishes: integrations.tested

What it writes: integration_account (update) — Last test time and result; integration_run (insert) — The test in the run history

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/record_test \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"ok":true,"message":"What happened"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.tested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.recordTest("INTEGRATION_ACCOUNT_ID", {
  ok: true,
  message: "What happened"
})
era integration_accounts record_test INTEGRATION_ACCOUNT_ID \
  --ok true \
  --message "What happened"
tools/call
{
  "name": "era__integrations__record_test",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "ok": true,
    "message": "What happened"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found · 429 slow down

integrations.reply_review

Reply to a review — Posts the business’s public reply to a Google review (replaces an earlier reply); sent in the background.

Needs integrations:write · reaches outside (sends, publishes or charges) · asks a person to confirm when Era runs it

POSThttps://app.getera.io/api/v1/integration_reviews/{id}/actions/reply_review
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.reply_review

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Review · id of integration_review
textstringyesReply · At most 4,000 characters (Google’s limit).

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe review must exist.
reply_emptyThe reply must say something.
reply_too_longAt most 4,000 characters.
account_inactiveThe review’s account must be connected.
reply_in_flightOne reply at a time per review.

Events it publishes: integrations.review_reply_requested

What it writes: integration_review (update) — Keeps the reply and marks it on its way

curl -X POST https://app.getera.io/api/v1/integration_reviews/INTEGRATION_REVIEW_ID/actions/reply_review \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"text":"Reply"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.review_reply_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationReviews.replyReview("INTEGRATION_REVIEW_ID", {
  text: "Reply"
})
era integration_reviews reply_review INTEGRATION_REVIEW_ID \
  --text "Reply"
tools/call
{
  "name": "era__integrations__reply_review",
  "arguments": {
    "id": "INTEGRATION_REVIEW_ID",
    "text": "Reply"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, reply_empty, reply_too_long, account_inactive, reply_in_flight · 429 slow down

integrations.request_sync

Sync now — Fetches new orders and products from a marketplace or shop and sends Era’s stock back — in the background, in seconds.

Needs integrations:write · changes data

POSThttps://app.getera.io/api/v1/integration_runs/actions/request_sync
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.request_sync

Input

FieldTypeRequiredNotes
iduuidAccount · id of integration_account
providerstringApp · Instead of the id: trendyol, hepsiburada, amazon, shopify, woocommerce, n11, ciceksepeti, ikas, ticimax, ideasoft, etsy. · max 41
feedstring (enum)What · orders = fetch new orders, stock = send Era’s stock, products = re-read listings, all = everything. · Allowed values: orders, products, stock, reviews, all
triggerstring (enum)Asked by · Allowed values: manual, era, schedule, webhook, connect, event

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist (by id, or the one account of the named app).
ambiguous_accountNamed by app, there must be exactly one account of it.
not_syncableOnly marketplaces, shops and review providers sync on their own.
disconnectedA disconnected account does not sync.
pausedA paused account does not sync.
sync_runningOne run of a feed at a time.

Events it publishes: integrations.sync_requested

What it writes: integration_run (insert) — The run, which the worker picks up

curl -X POST https://app.getera.io/api/v1/integration_runs/actions/request_sync \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"id":"INTEGRATION_ACCOUNT_ID"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.sync_requested"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationRuns.requestSync({
  id: "INTEGRATION_ACCOUNT_ID"
})
era integration_runs request_sync \
  --id "INTEGRATION_ACCOUNT_ID"
tools/call
{
  "name": "era__integrations__request_sync",
  "arguments": {
    "id": "INTEGRATION_ACCOUNT_ID"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, ambiguous_account, not_syncable, disconnected, paused, sync_running · 429 slow down

integrations.resolve_issue

Close a sync issue — Marks it resolved (fixed) or ignored (not a problem).

Needs integrations:write · changes data

POSThttps://app.getera.io/api/v1/integration_issues/{id}/actions/resolve_issue
API key or OAuth token · integrations:write
  • Canonical address: POST /api/v1/actions/integrations.resolve_issue

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Issue · id of integration_issue
statusstring (enum)Close as · Allowed values: resolved, ignored

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe issue must exist.
already_closedAn issue is closed once.

Events it publishes: integrations.issue_resolved

What it writes: integration_issue (update) — Closes it

curl -X POST https://app.getera.io/api/v1/integration_issues/INTEGRATION_ISSUE_ID/actions/resolve_issue \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"status":"resolved"}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.issue_resolved"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationIssues.resolveIssue("INTEGRATION_ISSUE_ID", {
  status: "resolved"
})
era integration_issues resolve_issue INTEGRATION_ISSUE_ID \
  --status "resolved"
tools/call
{
  "name": "era__integrations__resolve_issue",
  "arguments": {
    "id": "INTEGRATION_ISSUE_ID",
    "status": "resolved"
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:write · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, already_closed · 429 slow down

integrations.set_paused

Pause or resume syncing — A paused account keeps everything; nothing is fetched or pushed until it is resumed.

Needs integrations:manage · changes data

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/set_paused
API key or OAuth token · integrations:manage
  • Canonical address: POST /api/v1/actions/integrations.set_paused

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Account · id of integration_account
pausedbooleanyesPaused

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
disconnectedA disconnected account is connected again, not resumed.

Events it publishes: integrations.paused, integrations.resumed

What it writes: integration_account (update) — Flips paused / active

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/set_paused \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"paused":true}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.paused",
    "integrations.resumed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.setPaused("INTEGRATION_ACCOUNT_ID", {
  paused: true
})
era integration_accounts set_paused INTEGRATION_ACCOUNT_ID \
  --paused true
tools/call
{
  "name": "era__integrations__set_paused",
  "arguments": {
    "id": "INTEGRATION_ACCOUNT_ID",
    "paused": true
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, disconnected · 429 slow down

integrations.update_settings

Change what an app syncs — Orders in, products in, stock out, the stock buffer, how far back to look.

Needs integrations:manage · changes data

POSThttps://app.getera.io/api/v1/integration_accounts/{id}/actions/update_settings
API key or OAuth token · integrations:manage
  • Canonical address: POST /api/v1/actions/integrations.update_settings

Input

FieldTypeRequiredNotes
iduuidyesFilled from the path {id} · Account · id of integration_account
settingsobject / arrayWhat to sync
configobject / arrayAccount settings
labelstringName · max 160
warehouseIduuidWarehouse · id of warehouse

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
disconnectedA disconnected account is connected again, not edited.
bad_settingOnly known sync settings, with sensible values.

Events it publishes: integrations.settings_changed

What it writes: integration_account (update) — Merges the settings

curl -X POST https://app.getera.io/api/v1/integration_accounts/INTEGRATION_ACCOUNT_ID/actions/update_settings \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"settings":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.settings_changed"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.integrationAccounts.updateSettings("INTEGRATION_ACCOUNT_ID", {
  settings: {}
})
era integration_accounts update_settings INTEGRATION_ACCOUNT_ID --data '{"settings":{}}'
tools/call
{
  "name": "era__integrations__update_settings",
  "arguments": {
    "id": "INTEGRATION_ACCOUNT_ID",
    "settings": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:manage · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, disconnected, bad_setting · 429 slow down

integrations.upsert_listings

Record listings — Stores what a channel sells and ties each listing to an Era variant by SKU, barcode or external key.

Needs integrations:handle · changes data

POSThttps://app.getera.io/api/v1/channel_listings/actions/upsert_listings
API key or OAuth token · integrations:handle
  • Canonical address: POST /api/v1/actions/integrations.upsert_listings

Input

FieldTypeRequiredNotes
accountIduuidyesAccount · id of integration_account
listingsobject / arrayyesListings

Preconditions

The action is refused with 409 and one of these codes:

CodeRefused when
not_foundThe account must exist.
malformed_listingsA list of at most 1000 listings, each with a key.

Events it publishes: integrations.listings_synced

What it writes: channel_listing (upsert) — One row per listing; a match is never undone by a re-read

curl -X POST https://app.getera.io/api/v1/channel_listings/actions/upsert_listings \
  -H "Authorization: Bearer $ERA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{"accountId":"INTEGRATION_ACCOUNT_ID","listings":{}}'
Response
{
  "ok": true,
  "result": "…",
  "events": [
    "integrations.listings_synced"
  ]
}
import { createEra } from "@getera/sdk"

const era = createEra({ apiKey: process.env.ERA_API_KEY })
const res = await era.channelListings.upsertListings({
  accountId: "INTEGRATION_ACCOUNT_ID",
  listings: {}
})
era channel_listings upsert_listings --data '{"accountId":"INTEGRATION_ACCOUNT_ID","listings":{}}'
tools/call
{
  "name": "era__integrations__upsert_listings",
  "arguments": {
    "accountId": "INTEGRATION_ACCOUNT_ID",
    "listings": {}
  }
}

Errors: 401 no or expired credential · 403 the credential does not hold integrations:handle · 404 the record or module is outside what it may reach · 422 invalid input (problems[]) · 409 not_found, malformed_listings · 429 slow down

Data models

CarrierShipment

Table carrier_shipment · Resource carrier_shipments

  • GET /api/v1/carrier_shipments
  • GET /api/v1/carrier_shipments/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
order_idstring (uuid) · uuidyessales_order
referencestring · text
carrierstring · text
tracking_numberstring · textyes
barcodestring · textyes
label_urlstring · textyes
tracking_urlstring · textyes
statusstring · textrequested, created, in_transit, delivered, returned, cancelled, failed
last_eventstring · textyes
last_event_atstring (date-time) · timestamptzyes
receiverobject · jsonb
piecesinteger · int4
desistring (decimal) · numericyes
cod_amountstring (int64) · int8yes
errorstring · textyes
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Unique: account_id, reference

Checks:

  • CHECK (((cod_amount IS NULL) OR (cod_amount >= 0)))
  • CHECK ((pieces >= 1))
  • CHECK ((reference ~ '^[A-Za-z0-9-]{4,40}$'::text))

ChannelListing

Table channel_listing · Resource channel_listings

  • GET /api/v1/channel_listings
  • GET /api/v1/channel_listings/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
external_keystring · text
external_product_idstring · textyes
external_variant_idstring · textyes
skustring · textyes
barcodestring · textyes
titlestring · text
variant_namestring · textyes
urlstring · textyes
image_urlstring · textyes
item_variant_idstring (uuid) · uuidyesitem_variant
match_sourcestring · textyessku, barcode, reference, manual, created
remote_quantityinteger · int4yes
remote_pricestring (int64) · int8yes
currencystring · bpcharyesmax 3
last_pushed_quantityinteger · int4yes
last_pushed_atstring (date-time) · timestamptzyes
push_errorstring · textyes
is_activeboolean · bool
seen_atstring (date-time) · timestamptz
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz
metaobject · jsonb

Primary key: id

Unique: account_id, external_key

Checks:

  • CHECK ((length(external_key) > 0))
  • CHECK (((remote_price IS NULL) OR (remote_price >= 0)))

EinvoiceDocument

Table einvoice_document · Resource einvoice_documents

  • GET /api/v1/einvoice_documents
  • GET /api/v1/einvoice_documents/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
order_idstring (uuid) · uuidyessales_order
kindstring · texte_archive, e_invoice, draft
statusstring · textqueued, draft, issued, failed, cancelled
external_idstring · textyes
document_numberstring · textyes
pdf_urlstring · textyes
errorstring · textyes
total_amountstring (int64) · int8yes
currencystring · bpcharyesmax 3
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz
issued_atstring (date-time) · timestamptzyes

Primary key: id

IntegrationAccount

Table integration_account · Resource integration_accounts

  • GET /api/v1/integration_accounts
  • GET /api/v1/integration_accounts/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
providerstring · text
categorystring · textmarketplace, ecommerce, payment, shipping, einvoice, messaging, google, microsoft, accounting
labelstring · text
channel_idstring (uuid) · uuidyeschannel
warehouse_idstring (uuid) · uuidyeswarehouse
statusstring · textactive, paused, error, disconnected
configobject · jsonb
settingsobject · jsonb
cursorsobject · jsonb
last_sync_atstring (date-time) · timestamptzyes
last_order_sync_atstring (date-time) · timestamptzyes
last_product_sync_atstring (date-time) · timestamptzyes
last_stock_push_atstring (date-time) · timestamptzyes
last_test_atstring (date-time) · timestamptzyes
last_test_okboolean · boolyes
last_test_messagestring · textyes
last_errorstring · textyes
consecutive_failuresinteger · int4
created_bystring (uuid) · uuidyesapp_user
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Unique: webhook_token

Checks:

  • CHECK ((consecutive_failures >= 0))
  • CHECK ((length(TRIM(BOTH FROM label)) > 0))
  • CHECK ((provider ~ '^[a-z][a-z0-9_]{1,40}$'::text))

IntegrationInbound

Table integration_inbound · Resource integration_inbounds

  • GET /api/v1/integration_inbounds
  • GET /api/v1/integration_inbounds/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
external_idstring · text
topicstring · textyes
statusstring · textaccepted, rejected
reasonstring · textyes
received_atstring (date-time) · timestamptz

Primary key: id

Unique: account_id, external_id

IntegrationIssue

Table integration_issue · Resource integration_issues

  • GET /api/v1/integration_issues
  • GET /api/v1/integration_issues/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
kindstring · textunmatched_line, unmatched_listing, stock_short, push_refused, status_unknown, order_failed, auth, rate_limit, config, shipment_failed, einvoice_failed, webhook_rejected
external_refstring · text
item_variant_idstring (uuid) · uuidyesitem_variant
order_idstring (uuid) · uuidyessales_order
messagestring · text
detailobject · jsonb
statusstring · textopen, resolved, ignored
occurrencesinteger · int4
first_seen_atstring (date-time) · timestamptz
last_seen_atstring (date-time) · timestamptz
resolved_atstring (date-time) · timestamptzyes
resolved_bystring (uuid) · uuidyesapp_user

Primary key: id

Checks:

  • CHECK ((occurrences >= 1))

IntegrationReview

Table integration_review · Resource integration_reviews

  • GET /api/v1/integration_reviews
  • GET /api/v1/integration_reviews/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
providerstring · text
external_idstring · text
location_namestring · text
location_titlestring · textyes
ratinginteger · int2yes
commentstring · textyes
reviewer_namestring · textyes
reviewed_atstring (date-time) · timestamptzyes
reply_textstring · textyes
replied_atstring (date-time) · timestamptzyes
reply_statusstring · textnone, sending, sent, failed
reply_draftstring · textyes
reply_errorstring · textyes
created_atstring (date-time) · timestamptz
updated_atstring (date-time) · timestamptz

Primary key: id

Checks:

  • CHECK (((length(external_id) >= 1) AND (length(external_id) <= 500)))
  • CHECK ((provider ~ '^[a-z][a-z0-9_]{1,40}$'::text))
  • CHECK (((rating >= 1) AND (rating <= 5)))

IntegrationRun

Table integration_run · Resource integration_runs

  • GET /api/v1/integration_runs
  • GET /api/v1/integration_runs/{id}
ColumnTypeNullableAllowed valuesReferences
idstring (uuid) · uuid
organization_idstring (uuid) · uuidorganization
workspace_idstring (uuid) · uuidworkspace
account_idstring (uuid) · uuidintegration_account
feedstring · textorders, products, stock, webhook, test, shipments, einvoice, reviews
triggerstring · textschedule, manual, webhook, era, connect, event
statusstring · textrunning, ok, partial, failed, skipped
started_atstring (date-time) · timestamptz
finished_atstring (date-time) · timestamptzyes
countsobject · jsonb
messagestring · textyes
job_idstring (uuid) · uuidyes
created_bystring (uuid) · uuidyesapp_user

Primary key: id

Events

Workflows and webhooks react to these events.

EventWhat happensPayload
integrations.connectedAn app account was linked for syncing.id, provider, category, channelId
integrations.disconnectedAn account stopped syncing for good.id, provider
integrations.einvoice_requestedAn e-invoice was asked for an order.id, accountId, orderId
integrations.einvoice_updatedAn e-invoice was issued or failed.id, orderId, status, documentNumber
integrations.issue_raisedSomething needs a person (unmatched SKU, refused push, …).id, accountId, kind, message
integrations.issue_resolvedAn issue was resolved or ignored.id, accountId, kind, status
integrations.listing_mappedA listing was tied to an Era product by hand.id, accountId, itemVariantId
integrations.listing_publish_requestedProduct variants were queued for marketplace publication.id, accountId, mode, listings, userId
integrations.listings_syncedListings were read and matched to products.id, provider, seen, matched, unmatched
integrations.pausedAn account was paused; nothing syncs.id, provider
integrations.resumedA paused account was switched back on.id, provider
integrations.review_repliedThe provider published (or refused) a review reply.id, accountId, ok
integrations.review_reply_requestedA public reply to a review is on its way to the provider.id, accountId
integrations.reviews_syncedReviews were read from a review provider (Google Business Profile).id, provider, created, updated
integrations.run_finishedA sync, push or test finished.id, accountId, provider, feed, status, counts, message
integrations.settings_changedWhat an account syncs changed.id, provider
integrations.shipment_requestedA parcel was booked with a carrier.id, accountId, orderId, carrier, reference
integrations.shipment_updatedA parcel’s carrier status changed.id, orderId, status, trackingNumber
integrations.stock_pushedEra’s stock was sent to a channel.id, provider, pushed, failed
integrations.sync_requestedA sync was asked for (a person, Era, a webhook or the schedule).id, provider, feed, trigger, runId
integrations.testedA connection test ran.id, provider, ok, message
integrations.webhook_receivedA provider nudged Era that something changed.id, accountId, provider, topic
Was this page helpful?