API integrations

Make the systems you already use work together.

Important information and actions sit in products that do not naturally share them. PrimeLabs builds the application layer that exchanges the right data and triggers the right action, so people stop copying it by hand. A reliable integration has a contract, a failure path, a state and a history. It is not a promise that every product connects at once.

What the words mean in practice

  • API

    A defined way for one system to ask another for data, or to request a change. The other system decides what it will allow.

  • Webhook

    The other system calls you when something has happened, instead of you asking on a timer.

  • Read

    Take information in. The source record is unchanged.

  • Write

    Change a record somewhere else. That is the step with consequences.

  • Event

    A named thing that happened: a payment, an upload, a status change. The event is not itself the write.

  • Synchronisation

    Keeping an agreed set of fields current. It is not a licence to mirror every column in both directions.

  • Transformation

    Turning one system’s shape of a customer, a date or an amount into the shape the other system expects.

A read is not a write

Reading a customer, an invoice or a payment is how an application stays informed. Proposing a change is the prepared payload: the fields, the identifiers, the checks that already passed. Performing the write is the call that alters the other system.

Not every write needs a person. A low-risk update that the contract allows can run once the checks pass. A write with business impact deserves more care: validation, a precondition that must still be true, approval where the cost of a mistake is high, a repeat that does not create a second record, and a history of what was sent. Doing the step twice must not produce two payments. That is the practical test. Engineers call the property idempotency.

The example on this page holds an accounting write for that reason. The payment event has arrived. The invoice matches. The write has not been sent.

One morning of exchanges, with a write still held

This hub is an example, not a client integration. Select an event. The accounting payment can be approved here. The message stays on this page.

Example interface. Not a client project.

Integration hub · CRM, accounting, payments, email, document storage

Create payment for INV-1048

Ready for review

Source
PrimeLabs
Destination
Accounting
Operation
Write payment
External ID
Not sent
Internal record
Invoice INV-1048
Request
Prepared payment: PI-8401, 1,840.00 AUD, customer C-1842.
Response
Nothing has been posted. The destination has not been called.
Validation
Invoice amount matches. Customer record exists. Payment provider reference is present. Accounting write has not been sent.
Retries
0

One system should own each field

An integration needs a plain answer to who owns the record. If two products can both change the same phone number, the next sync becomes an argument. Ambiguous two-way ownership is how stale and duplicate records appear.

A workable split is ordinary: the CRM owns the customer contact, the accounting system owns the invoice, and the PrimeLabs application coordinates the process that uses both. It may store a copy for the screen the staff or the customer sees. It does not become a second ledger, or a second CRM, unless that was the decision.

That coordination is often what an internal business application or a customer portal needs. The portal can show an invoice status it does not own. The internal tool can show a customer it does not own. The integration is how those reads, and any later write, stay honest.

The same fact rarely has the same name

A customer id in one product is an account id in another. Status words differ. Dates arrive in more than one format. Money may be dollars in one payload and cents in the next. Addresses are one line or five. Product codes and user identifiers diverge as soon as two vendors are involved.

Mapping is the explicit table of those differences, plus the checks that reject a value the destination cannot store. Without it, a successful HTTP call can still write the wrong record. Feasibility depends on the source system’s API, its permissions, its rate limits and its data model. Naming a product here is not a claim that it is already connected.

A webhook says something happened. It does not authorise the next write.

A payment succeeded. A document was uploaded. A customer was updated. A booking changed. An invoice was marked paid. An application was approved. Those are useful events. Receiving one means the integration can wake up, check the signature, find the internal record, and decide what is allowed next.

The decision can be “record this and stop”, “queue a later step”, or “prepare a write and wait”. Blindly posting to a second system because a webhook arrived is how a duplicate or a forged event becomes a real change. Where the next step is a long run with retries and a person, that belongs with workflow automation. Where the event is a file, the reading of that file is a document workflow, and only an approved result should be written downstream.

Failure should be a state, not a disappeared request

Providers time out, limit bursts, and have outages. A retry is right for a temporary failure, with a limit, and with the same identity so a second attempt does not create a second payment or customer. A rate limit is a reason to slow down, not to hammer the endpoint.

Duplicate delivery is normal. Webhooks are often sent more than once. The handler has to recognise an event it has already accepted. When retries are exhausted, or the payload is rejected for a reason that will not change, the event waits for a person. Some teams call that a dead letter. The useful version is a row someone can open, with the error and the record it belongs to. The history of attempts stays either way.

Someone should be able to see what the integration did

A useful history answers what happened, when, to which record, which provider, whether it succeeded, whether it was tried again, and whether a person still needs to act. That is the screen in the example: a morning of events, one write held, one retry scheduled.

Without that record, a failed status update looks like the CRM “just didn’t update”, and the only investigation is someone’s memory of a script. Observability here is not a separate monitoring product. It is the integration keeping its own account of each exchange.

A path that uses only the pieces the exchange needs

Cloudflare can host this. It is not the subject of the page. Which services belong, and which do not, is on Cloudflare application development.

  • External systemThe CRM, ledger, payment provider, identity platform, mail system, document store, shop, booking tool, membership product, line-of-business API, or an internal database. Only where that system actually offers a usable interface.
  • Webhook or API requestSomething arrives, or the application asks. The browser does not hold the credential.
  • WorkerVerify, map, and decide. Short work.
  • D1The event, the mapped identifiers, the current state, and whether a write is still held.
  • Queue or WorkflowA burst of events, a retry, or a wait for approval. Not required for a single read that finishes in the request.
  • DestinationThe write, if it is allowed. Then the history of what came back.
  • Left out unless neededDurable Objects for a single lock or counter. KV for a short-lived check, not for the ledger of events. R2 when the exchange includes a file, not when it is only fields.

Credentials stay on the server, and writes stay narrow

API keys and tokens are secrets on the Worker, not in the browser and not in the page. Each credential should have the smallest permission that the exchange needs. A key that can read customers should not also be able to refund payments. Webhooks are checked with the provider’s signature before the payload is trusted.

Tokens get rotated. The application should tolerate that rotation without a redeploy being the only plan. Write permission is separate from read permission, and the audit trail shows who or what approved a write. The web application around the integration is what enforces that boundary.

The other system sets limits. The design has to live with them.

Providers impose request quotas, burst limits, operations they simply do not offer, data that is briefly stale, pagination, outages, and scopes that do not include the field you wanted. PrimeLabs designs the exchange around those constraints. Polling harder does not create an endpoint the vendor did not publish.

Not every exchange should be instant. An immediate event suits a payment or an approval. A queue suits a burst. A schedule suits a nightly reconciliation. A person can refresh one record when they are looking at it. The right model is the one the business actually needs, not the fastest one that can be drawn.

A model may explain a failure. It does not post the payment.

Inside an integration, a model can classify an unstructured note, suggest a match between two descriptions of the same customer, summarise why a call failed, or draft the reconciliation a person will confirm. It does not hold credentials, invent identifiers, choose a financial write, skip validation, or replace the provider’s contract.

Identifiers, amounts and allowed operations stay in ordinary code. How that boundary is drawn more generally is AI application development.

When an integration fits

Build it

  • The other system has an API or a webhook you are allowed to use.
  • People copy the same fields on a recurring basis.
  • The application’s state depends on data it does not own.
  • An event can replace a manual check or a constant poll.
  • More than one system has to act in a defined order.
  • Someone will need to see what was written, and whether it failed.
  • Reliability matters more than a one-off script.

Leave it

  • There is no usable API, export or event, and the vendor will not add one.
  • A native connection already does this job well.
  • The exchange is rare, and doing it by hand is still cheap.
  • The provider’s rules block the operation you need.
  • Nobody can yet say which system owns the field.
  • The only remaining path is driving a browser, and that is too fragile for the requirement.

Start from one exchange that people already retype

A useful first note names the two systems, the field that is copied, which one owns it, whether the change is a read or a write, and what should happen when the call fails. There is no account on this website.

Discuss an integration

Straight answers

Will you connect every product we use?

No. Each connection depends on that product’s API, permissions, limits and data model. The first version is usually one exchange that is already being retyped.

Does every write wait for a person?

No. A write waits when the impact justifies it, or when a check has not passed. A read does not wait for approval of a change that is not being made.

Can a webhook update our accounts by itself?

Only if that update is in the contract and the checks pass. Receiving the event is not the same as being allowed to write.