# PalDock > Performance Marketing Software ### Posts #### Always-Up-To-Date Marketing Assets Always-Up-To-Date Marketing Assets Take full control over your marketing assets with easy management of expiration dates and post-expiration content. Say goodbye to outdated banners or information on affiliate sites. Affiliates can enjoy the benefits of auto-updating HTML banners or tap into real-time product feeds—perfect for comparison websites. #### Automate Product Data with Advanced Aggregation Automate Product Data with Advanced Aggregation Product comparison is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds including your own for easy comparison on your sites. The best part? Updates sync automatically with advertiser XML changes, but you also have the flexibility to tweak things manually. #### Boost Clicks with the fastest URL shortener to create short branded links Boost Clicks with the fastest URL shortener to create short branded links Lengthy, messy links can seriously harm your click-through rates. People either hesitate to click on them or get stuck in slow redirects. Paldock’s here to change the game. Turn those lengthy URLs into neat, branded links that represent your website with grace. With a direct connection to both your site and advertisers, we ensure super-fast redirects, beating any other URL-shortening tools. And the icing on the cake? Change a shortened link once, and it updates across multiple sites. No tedious, site-by-site changes. A real time-saver! #### Boost effectiveness and revenues by Lead generation Boost effectiveness and revenues by Lead generation Think beyond just clicks! Dive into leads as a powerful traffic source and track everything on a single, unified platform. Make the process more efficient: equip affiliates with ready-to-embed customizable forms for their sites or an API for direct lead submissions to Paldock, and, ultimately, to you. Craft the perfect lead journey with our intuitive drag-and-drop editor, packed with lead validation, verification, and advanced filtering. Bonus: If your affiliate is already on Paldock, you’re in for a smooth setup, potentially saving weeks of API integration time. #### Boost Your Earnings with Lead Generation Boost Your Earnings with Lead Generation Sending clicks to advertisers is decent, but let’s face it, it’s like throwing darts in the dark. You can’t really steer the conversion once it’s on their website. Here’s where Lead Generation shines. Instead of just routing clicks with unpredictable outcomes, why not gather leads directly on your site and pass on this valuable data? It’s a win-win-win! Your visitors get extra value, you grow a robust database, and essentially, you’re crafting your very own product and the Advertiser is happy for a hot lead. Think about it: if you’re promoting services, say loans, you can collect user info and match them with the perfect loan offer. The result? A significant revenue increase, as a solid lead far outvalues a mere redirect. #### Brand Safety Rules for Networks Brand Safety Rules for Networks For advertisers keen on brand protection, you can provide traffic exclusively from whitelisted domains based on their choosing. With Paldock, they’ll also be able to pinpoint the exact page from where the traffic originates, facilitating their possible review process. Furthermore, if required, affiliate partners can be prompted to sign the extra advertiser’s terms and conditions. And should advertisers wish to have a hands-on approach, you can enable them to communicate with and manage affiliates directly. #### Bring your revenues back with Cookie-less tracking Bring your revenues back with Cookie-less tracking Did you know? On average, only 60% of users allow cookie tracking through consent bars. If your advertiser relies solely on cookies, that’s a whopping 40% of potential revenues slipping away from you. But Paldock has a solution. With our Postback tracking, we bypass cookies altogether, ensuring every conversion and every cent is captured. PalDock ensures every possible dollar lands in your pocket. #### Build your own products to get an edge over competitors Build your own products to get an edge over competitors Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Considering a Product or Service Comparison? How about a recommendation engine tailored to user inputs? Whatever you envision, we’ve got the tools. Integrate with Advertisers via API, gather all the essential data, and turn those connections to your advantage. #### Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Summary Dostartu, a European virtual office broker, designed its project to solve a specific problem: authorities don’t view all company addresses the same. A risky address can put a business on the government’s radar – often because it’s crowded with VAT debtors, insolvent firms or their directors, and even companies with criminal convictions. For a long time, it was difficult to see which addresses were safe and which weren’t. Their platform now makes those risks visible and helps clients avoid problematic locations. Why affiliate links alone were not enough On smaller markets and in niche segments, the conversion to actual sale is everything. And plain affiliate links that just redirect to advertisers’ websites simply fall short. Roughly 40% of visitors don’t give consent to cookie tracking (YouGov global consumer study), which means an instant 40% revenue loss for the broker. On top of that, the broker has zero control over the conversion rate on the advertiser’s website. Dostartu knew that, as a broker, they needed full control over conversion to be successful. With lead generation, they can influence every step needed to create a lead, and they get 100% transparent, trustworthy data about their traffic. Every lead is tracked and every lead has a status. There’s also another problem: advertisers can fail to report all sales, whether due to a technical issue or knowingly. With a click, they simply have to trust the advertiser. With a lead, they can verify the sale themself. Starting a Lead gen heavy project from a scratch without any developer To launch something this technical, you’d normally need a developer. Dostartu didn’t. They used PalDock, where most of the heavy lifting is already done. Instead of spending months: integrating business registries to check multiple risk indicators for each address and connecting 20+ APIs of virtual office providers, building a comparison engine with automatically updated data, filters, sorting and custom calculations, setting up an affiliate-ready comparison that partners can promote using affiliate links or by embedding the comparison on their own websites, and developing a way for affiliates to send leads, integrating the business registry to prove that each customer really moved their company to the selected virtual office and to make their commission claim unquestionable for the advertiser, …they plugged PalDock into their WordPress site, installed the PalDock Comparison Plugin, and focused on the business, not on code. “We went from idea to a live comparison and affiliate setup in a few days, without hiring a single developer. And we’re no longer dependent on trusting advertisers to set up tracking correctly or report sales honestly – we control the whole flow ourselves and see everything automatically.” Dostartu’s Project Manager, Jakub Bil How they did it With PalDock, the setup was straightforward. They consolidated data feeds from multiple providers. Instead of maintaining an Excel table and updating it manually every month, they managed everything in PalDock. Each advertiser had its own product feed, and a single Pingtree offer consolidated all feeds into one. This made website updates much easier and allowed them to share the same automatically updated feed with their affiliates. For data and comparison display, they used the PalDock WordPress plugin to present everything on their website with a fully custom design. From there, they routed visitors through affiliate links and, most importantly, embedded forms. In PalDock, they could build forms with any design and validation rules they needed, such as phone and email checks. To keep the form as simple as possible, they did not ask users to enter full company details. Instead, they used a company name autocomplete to capture a verified name, then pulled the remaining data automatically with a second lookup. Both calls were handled inside PalDock, first an API request to suggest companies as the user types, then a second request to fetch all available data once a company is selected. This kept the form short and frictionless. Instead of waiting for developers, they used PalDock’s built-in integration tools to connect to virtually any API. This let them send leads from embedded forms or via API to advertisers, even when each advertiser required a different setup, including mapping and transforming lead data to match each advertiser’s schema. They also used the integration tool for field validation, autocomplete, data enrichment, and conversion tracking. Thanks to PalDock, this did not take weeks or dozens of developer hours. It took only a few hours of configuration. Because the forms collect company details, they could automatically and regularly verify with another API request whether a company had changed its registered office, trigger payment requests to the provider, and approve conversions for affiliates. They also integrated several public registries to assess the quality of each office address. In the end, they enriched their feed with dozens of additional data points, delivering more value to visitors and creating stronger angles for promotion. The key advantage was speed and scalability. They could replicate the same setup across affiliate partners’ websites and start receiving relevant traffic right away. By offering a genuinely strong comparison experience enriched with dozens of extra data points, they became a partner that affiliates actually wanted to promote, including partners they would not normally reach. On top of that, automated conversion tracking was a major win for everyone involved. No conversions were missed, and there was no need to wait for an advertiser’s confirmation because results were captured immediately and reliably. With PalDock, they had complete visibility into every lead and conversion. They always knew which advertiser each lead was sold to, what conversions were created, and how each transaction performed. This level of insight was available not only for their own traffic and website, but also across all affiliate partners, giving them full control and transparency over the entire flow. How they found the best value for the money But coming back to the platform choice, they didn’t take shortcuts or settle for a half-baked solution. With their entire project on the line, they analysed the whole market and every tool they could find and ended up with a clear winner. PalDock was the only platform powerful enough to cover all their requirements, yet simple enough to run without a developer. Here’s what made the difference: Links and lead generation in one place: Affiliates who like links can keep running link campaigns, while the same platform also handles embedded comparisons and forms, API-based leads and lead routing, so everyone works in one system with one set of numbers. Standardised affiliate API with ready-made templates: PalDock standardises API integrations for affiliates, cutting integration time from weeks to a few minutes. Instead of building a new custom integration for each buyer, affiliates can reuse previously prepared API templates and start sending traffic in a few clicks. Embeddable and fully customisable comparisons and forms: Less technical partners who cannot or do not want to integrate via API can simply embed auto-updated comparison widgets and lead forms on their site, adjust the look to match their brand and start sending leads without touching any back-end logic. Accurate, real-time tracking without relying on cookies: PalDock supports cookieless tracking for both clicks and leads, so everyone sees 100% of their conversions and up-to-date sales data, enabling campaign optimisation based on what actually gets approved instead of guessing from end-of-month reports. Flexible lead validation and data enrichment: The broker can define detailed validation and pre-screening before accepting a lead and automatically enrich or prefill lead data from external sources, so users don’t have to fill in everything manually and the data is 100% verified. As a result, they only receive leads they can realistically convert, while affiliates get fast feedback and more stable earnings per approved lead. Shared dashboards for easier debugging and less support: Partners and advertisers have direct access to their own dashboards, so they can see traffic, leads and sales in real time. Feedback from affiliates For many affiliates, this project finally gave them a smart way to monetise sites that either had no suitable offer before or were monetised poorly. Thanks to the easy implementation (embeds, links, ready-made flows), partners could go live quickly and plug the comparison into their existing content. Key Results & Benefits Since moving to PalDock, Dostartu: Built and launched the whole project without a developer and with minimal upfront costs. Instead of spending months on custom development, they had everything ready and live within a few days. From day one, they could buy traffic from paid campaigns and optimise in real time based on actual conversions, not guesses. At the same time, they could work with affiliates using classic links and lead-based campaigns, all tracked and reported in one place. Ready to grow? Discover how PalDock can help you scale your affiliate marketing operations without high costs. Request a demo today. #### Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Summary Leadgenia, an affiliate network in finance and insurance, built its business on links and simple CPA deals until they needed a way to grow beyond this model. They tested and proved that lead generation works well for affiliates, advertisers and the network, but the previous platform TUNE could not support proper validation, routing and flexible forms. After detailed research they chose PalDock, which brought links, lead forms, API integrations and ping tree routing into one platform, improved earnings for affiliates, delivered real qualified leads to advertisers and opened a new revenue stream for the network. From classic affiliate network to lead generation Leadgenia is a European affiliate network focused on finance and insurance. They work with both their own projects and a wide network of affiliate partners. The company started as a classic affiliate network built around lending offers, links and standard performance campaigns. This model worked, but it also came with clear limits. When your only product is clicks and simple CPA deals, there is a natural limit to how much you can earn. On top of that you have a limited competitive advantage for affiliates because your offers are the same as in other networks and affiliates simply send traffic where they get paid the most. “When you only sell clicks, you are easy to replace. Affiliates went wherever they got a slightly higher payout and we had almost no way to stand out.”Leadgenia’s Head of Affiliates, Vojtěch Potocký Why links alone were not enough anymore As a network built on clicks and classic affiliate links, Leadgenia had three main challenges ahead: Add a new revenue stream Offer a real competitive advantage for affiliates so they do not choose only by CPA amount Build their own product they could control, improve and upsell or cross sell to advertisers TUNE, the previous platform, was fine for links but weak for lead generation. It could embed simple scripts and track basic events, but: – It did not support real lead validation flows– It did not support ping tree or lead routing between multiple buyers– Embedded forms were hard to customise and maintain– Anything beyond links felt like a workaround and in practice it really was a workaround “At some point, we realised we did not need another set of campaigns with a different CPA. We needed our own product that we could shape, control and actually build a strategy around.” When leadgen made sense for everyone They quickly proved that the idea works and saw clear interest from both affiliates and advertisers, plus a real new revenue stream for the network. Affiliates care about how much they earn per click, not about the CPA amount by itself. An offer with a lower CPA can still make them more money if it converts better. With lead generation the network can finally influence and improve the conversion rate, because the lead generation offer is their own, not just a third party link. Advertisers are also ready to pay more for something more valuable than a click, in this case for a lead. On top of that, the network that collects these leads can monetise them further and earn extra margin that does not exist in a pure link business. All of this convinced them that lead generation should become a core part of their business. The only thing they still needed was a proper tool. How they found the best value for the money They did not take shortcuts. Instead they did the hard work and went through the market to analyse every tool they could find. After two months of research they narrowed the list down to five serious candidates. They tested free trials and compared features, pricing and everyday usability. In the end PalDock clearly came out on top. Links and lead generation in one place – Affiliates who like links can keep running link campaigns, while the same platform handles forms, API based leads and routing, so everyone uses one system and one set of reports. Integration tool for anything – PalDock can connect to any API through a simple integration builder, not only to send leads, but also to send or request data. No developer needed. Ping tree for lead routing – They can send every lead through a clear chain of buyers in different models such as (non)exclusive, auction or user choice, with filters, caps and fallback rules to see exactly where each lead ended up and why. Form builder they can really control – Leadgenia can build and adjust forms on their own using conditional fields, multi step flows and different variants per campaign without asking developers to change back end logic every time. Tracking that goes beyond pixels – They can track both clicks and leads through postbacks or through tracking API, which gives them more control, better data and fewer situations where they have to guess what happened. Product feeds for comparison projects – For affiliates or their own sites and comparison projects they can use product feeds so offers stay up to date automatically without outdated information and without constantly reminding partners to update content. “We were not looking for a new link tracker. We were looking for a platform that understands both affiliates and lead buyers and can handle the whole flow from click to sold lead.” Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Feedback from affiliates and advertisers Affiliates welcomed the change. Instead of one more click offer in a long list, they received new campaigns for the same audience that brought better earnings per click. On top of that, they could place the forms directly on their own sites, so they were no longer just sending traffic away. For many partners, this opened a new way to earn, not only through links but also through leads. Advertisers noticed the difference as well. Instead of paying for random visitors, they started getting real leads with all the important data in place. That immediately improved their approval rates and made their marketing spend more predictable and, as a result, increased payouts too. Having direct access to the platform helped them match numbers at the end of the month and spot any unusual trends much faster. For Leadgenia, this removed a lot of manual coordination between both sides. Less explaining and checking, more time to build new campaigns, onboard partners and grow the whole business. Key Results & Benefits Since moving to PalDock, Leadgenia: New revenue stream from lead generation on top of the original affiliate link business Own product they can control, improve and cross sell or upsell to advertisers One platform for links, forms, API leads and routing instead of workarounds and spreadsheets Smarter lead routing with ping tree, filters and caps which increases total revenue per lead and extra margin Less manual coordination between affiliates and advertisers so more time to build campaigns and grow the network For any network that wants to go beyond simple links and add serious lead generation on top, Leadgenia shows that the right platform can become real leverage for growth. “PalDock let us keep what already worked in our affiliate business and add serious lead generation on top. We did not have to choose between links and leads. We finally got both in one place.” Ready to grow? Discover how PalDock can help you scale your affiliate marketing operations without high costs. Request a demo today. #### Case study: How Lender Orka Ventures Scaled Affiliate Operations Summary Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. Their custom affiliate API and tracking layer soon turned into a blocker: every new market or serious partner meant one off development, debugging and they had no proper link tracking to work with classic web traffic alongside API leads. By switching to PalDock they replaced this fragmented setup with a single platform for both links and API leads, with standardised APIs, accurate tracking and real time reporting, so they can now focus on launching offers and scaling volumes instead of rebuilding tools in every market. In mature lending markets, 90% of new loans come via affiliate APIs Orka Ventures is a European multi-market online lending group that wanted to scale fast across several countries and bring affiliates on board quickly in each of them. Originally they relied on their own custom affiliate API and tracking layer, but every new market and every bigger partner meant more one off development, more debugging and more time lost on integrations and onboarding instead of growth. It slowly turned into a blocker for expansion. Maintaining separate custom setups was expensive, hard to standardise and demanding for affiliates who had to integrate yet another custom API. Because their setup was focused only on API based leads, Orka Ventures also had no real way to buy classic web traffic through affiliate links. They lacked a proper tool that could handle cookie consent, combine cookie and cookieless tracking and fairly attribute conversions to partners. Is there an all in one solution that could help? To remove this bottleneck, Orka Ventures decided to move away from custom infrastructure and switch to PalDock. Instead of building and maintaining their own affiliate stack in every market, they adopted a platform designed around standardised APIs, fast affiliate onboarding and multi market operations, so they could focus on launching offers and scaling volumes rather than reinventing the same tools again and again. “Since PalDock is designed for affiliates as well, integrating the standardized API is straightforward, allowing them to start sending leads within an hour.” Orka Ventures’s Director, Simone Bertolone Key Results & Benefits Since moving to PalDock, Orka Ventures got: Links and lead generation in one place: Affiliates who like links can keep running link campaigns, while the same platform handles embedded forms, API based leads and routing, so everyone works in one system with one set of numbers. Standardised affiliate API with ready made templates: PalDock standardises API integrations for affiliates, cutting integration time from weeks to a few minutes. Also, instead of building a new custom integration for each lender, affiliates can reuse previously prepared API templates to send traffic in 3 clicks. Accurate tracking without relying only on cookies: PalDock has cookieless tracking not only for clicks, but naturally also for leads, where affiliates track 100% of their conversions without any losses. Real time stats on approved loans and rejection reasons: Both Orka Ventures and affiliates see up to date data on issued loans and clear rejection reasons, which lets partners optimise campaigns based on what really gets approved instead of guessing from end of month reports. Flexible lead validation and pre check rules: The lender can define detailed validation and pre screening before accepting a lead, so they only receive leads they can realistically convert, while affiliates get fast feedback and more stable earnings per approved lead. Shared dashboards for easier debugging and less support: Partners have direct access to their own dashboards, so they can see traffic, leads and rejects in real time. Ready to grow? Discover how PalDock can help you scale your affiliate marketing operations without high costs. Request a demo today. #### Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Summary Silverside, an online lender in consumer finance, built its acquisition on affiliate links that sent traffic to its loan application on a simple CPA per approved loan. This worked for a while, but as the market matured they needed to adapt. They built a custom in house solution, which proved hard to maintain and improve and started to limit their growth. It also pulled internal resources away from their core lending business and was neither transparent for affiliates nor easy to integrate through a standard API. After detailed research they chose PalDock and replaced the custom tool with a platform that already reflects thousands of hours of experience from other lenders and industries, so they could grow on top of a proven setup instead of learning everything the hard way. In mature lending markets, 90% of new loans come via affiliate APIs Silverside is a European lender that works with individual affiliates as well as multiple affiliate networks. The company built its acquisition strategy on affiliate links that sent traffic to its loan application on a simple CPA per approved loan. This model worked well in some markets, especially in the early stages. As key markets matured, however, most of the volume from serious affiliate partners started to shift from simple click traffic to full lead generation through forms and APIs. In some mature lending markets, up to ninety percent of new loans from affiliates now come via APIs rather than traditional affiliate links. On top of that, up to 40% of traffic cannot be tracked at all due to missing cookie consent (YouGov global consumer study). Silverside realised that without its own lead generation flows it was leaving money on the table. They also knew they had a window of opportunity. Only a few lenders in their markets were ready for proper affiliate APIs, so moving early meant they could become a preferred partner before the channel turned into a commission war. “Although we are a small lender, a strong API and affiliate friendly features made us competitive and easy to work with. Affiliates could start quickly and we could buy leads on the same level as much bigger players. Thanks to background third party checks and lead validations, we could choose which leads to accept or reject. That way we stayed profitable while still paying an attractive CPL.” Silverside’s CEO, Pavel Strnádek When a custom solution feels like a good idea… but isn’t Like many other lenders, Silverside first built its own custom solution. On paper it looked perfect: full control and features tailored exactly to their needs. In practice it meant that affiliates had to integrate and debug yet another unique API on top of dozens they already worked with. Every lender behaved differently and when something broke there was no shared, transparent environment where both sides could easily see what was going on. There was no real time reporting of approved loans or rejection reasons, only exports and manual summaries, so partners had very limited data to optimise their campaigns. Internally the tool was also heavy on resources. It consumed limited IT capacity, cost a lot to maintain and every change or new feature requested by affiliates had to wait for development. That slowed down new integrations, delayed campaigns and blocked further growth, creating missed opportunities long before the custom solution was anywhere near “good enough” to support what the channel could really deliver. How they found the best value for the money They did not take shortcuts. They put in the work, looked across the market and analysed every tool they could find. After two months of research, testing free trials and comparing features, they narrowed the list down to a single option. In the end PalDock was the clear winner thanks to features such as: Links and lead generation in one place: Affiliates who like links can keep running link campaigns, while the same platform handles embedded forms, API based leads and routing, so everyone works in one system with one set of numbers. Standardised affiliate API with ready made templates: PalDock standardises API integrations for affiliates, cutting integration time from weeks to a few minutes. Also, instead of building a new custom integration for each lender, affiliates can reuse previously prepared API templates to send traffic in 3 clicks. Embeddable and fully customisable forms: Less technical partners who cannot or do not want to integrate via API can simply embed a form on their site, adjust the look and start sending leads without touching any back end logic. Accurate tracking without relying only on cookies: PalDock has cookieless tracking not only for clicks, but naturally also for leads, where affiliates track 100% of their conversions without any losses. Real time stats on approved loans and rejection reasons: Both Silverside and affiliates see up to date data on issued loans and clear rejection reasons, which lets partners optimise campaigns based on what really gets approved instead of guessing from end of month reports. Flexible lead validation and pre check rules: The lender can define detailed validation and pre screening before accepting a lead, so they only receive leads they can realistically convert, while affiliates get fast feedback and more stable earnings per approved lead. Shared dashboards for easier debugging and less support: Partners have direct access to their own dashboards, so they can see traffic, leads and rejects in real time. Feedback from affiliates Affiliates were genuinely happy with the change. Instead of pushing random clicks, they could finally send real leads, which are more tangible and valuable. That brought higher and more stable earnings per click, plus more total revenue from the same traffic. Thanks to embedded forms and API flows they gained real control over funnels and could watch approval rates per source, optimise on the fly and have less downtime when something went wrong. Their setup also became much simpler. Instead of fighting with another custom lender API, they could use a standardised integration or just embed a form, which meant faster and easier onboarding and integrations. With multiple ways to deliver customers to Silverside (links, forms, API leads), both sides could choose what worked best for each project and grow revenue on both sides of the partnership. Key Results & Benefits Since moving to PalDock, Silverside: Increased approved loan volume and revenue thanks to strong API connectivity and affiliate-friendly features. Made integrations fast and predictable by replacing the custom tool with one platform for links, forms and APIs, cutting onboarding time from weeks to minutes and reducing downtime. Gained accurate tracking, real time stats and rejection reasons, which helps affiliates improve traffic quality without adding extra IT workload. Ready to grow? Discover how PalDock can help you scale your affiliate marketing operations without high costs. Request a demo today. #### Centralize Conversion Insights Centralize Conversion Insights Drowning in data from a multitude of advertisers and networks? Bouncing between systems to keep tabs on conversions can be overwhelming. Paldock simplifies it all. We bring together results from every corner into a unified dashboard. Just one login, one platform, and you have it all at your fingertips. And if your advertisers use Paldock as well? Even better! Generate promotional content or send out invoices directly, no need to toggle between accounts. #### Efficiently Manage Your Affiliate Partners Efficiently Manage Your Affiliate Partners Seamlessly recruit, onboard, and organize your partners. Easily categorize and tag them, and assign dedicated affiliate managers for personalized attention. Tailor your commission structures to fit any model you desire – whether it’s CPA, CPS, or revenue sharing or use a commission formula (example). Plus, boost partner’s motivation with the flexibility of offering one-time or automated bonuses, and apply penalties when needed. Networks can also recruit and onboard advertisers, then categorize, tag, and allocate dedicated managers. Networks can also customize commission plans – be it CPA, CPS, revenue sharing, or any other model (including custom formulas)., but they can set distinct commission models for partners and advertisers. #### Effortless Link Management Effortless Link Management Juggling multiple affiliate links or websites? Things can get tangled fast. That’s where Paldock steps in. Centralize and manage all your affiliate links from a single hub, eliminating the hassle of going through countless posts or sites to make link updates. But we don’t stop there. We actively monitor link health, ensuring users are smoothly redirected to an alternative you’ve set up if a link breaks. And, of course, we’ll promptly notify you. #### Effortless Notifications for You and Your Affiliates Effortless Notifications for You and Your Affiliates Stay updated with automatic or manual notifications tailored for both you and your affiliate partners. Whether it’s about a new partner awaiting approval, a fresh payout request, or even just general communications, we’ve got you covered. Beyond the standard alerts, customize notifications to suit specific needs. Worried about traffic drops from top affiliates or potential link/API downtimes? Set up specialized alerts and always be a step ahead in managing any challenges. Networks can also use notifications for Advertisers. #### Enhance Promotions with Advanced API Features Enhance Promotions with Advanced API Features Empower your affiliate partners by offering them enhanced API functionality. Let them promote your products with precision by allowing them to check through API who’s eligible for your offerings. With our adaptable API, affiliates can easily verify details like location or user group eligibility before directing potential clients to you. It’s an ideal solution for services like internet connectivity and other products, which are not for everyone, everywhere. #### Free Affiliate tracking software Many companies (inlcuding YOU) search for free affiliate tracking software because they want to launch an affiliate program without committing to expensive monthly fees. The problem is that a reliable affiliate tracker is not just a simple tool that counts clicks and adds commissions to a spreadsheet. It requires servers, databases, tracking logic, security and ongoing maintenance. That is why truly unlimited and completely free affiliate tracking software is rare. However, “free” does not always mean a short-term trial or a limited demo. Some platforms offer free plans with enough functionality for smaller affiliate programs or early-stage testing, while others use different pricing models based on usage, revenue or infrastructure requirements. The important thing is understanding what you actually get for free, what limits apply and when a free solution stops being enough for your business. Is Free Affiliate Tracking Software Really Free? The short answer is: usually not. Every affiliate tracking platform needs infrastructure to run – servers, databases, storage, monitoring, security and continuous development. Even if the software itself is offered for free, someone still has to cover the costs of keeping it reliable and available. And when you process thousands of clicks or leads, those costs quickly add up. That being said, the need to test before committing or find the best possible deal is understandable. Free plans and trials are a great way to validate whether a platform fits your needs. Just keep in mind that paying for software is not only about access – it also supports ongoing maintenance, security updates and further development of the platform. What You Actually Need From Affiliate Tracking Software You probably already know what you need, but to summarize it, affiliate tracking software should answer one simple question. Which partner generated which result? When comparing free affiliate tracking platforms, check whether the free version actually includes the features you need. Some tools are free because they only cover a small part of the workflow. The essential features are: Click tracking – track affiliate traffic and sources Conversion tracking – connect clicks with leads, sales or registrations Commission management – calculate and manage payouts Affiliate management – handle partners, campaigns and access Reporting – understand performance and revenue Integrations – connect with your existing tools via API or postback It might not sound like rocket science, right? You might think: “Why not just build it yourself?” And for a basic internal tool, that can be a reasonable approach. But affiliate tracking is different as it handles revenue attribution, partner payouts and financial data. Building a reliable custom solution requires much more than a few screens and tracking scripts. The Problem With Building Your Own Free Affiliate Tracker With AI tools and vibe coding, building a basic free affiliate tracker has never been easier. You can create tracking links, dashboards and simple conversion logic in a matter of days. The problem is that affiliate tracking is not just another internal tool. It directly affects revenue attribution, partner payouts and trust. A small issue with tracking logic, duplicate conversions or security can quickly turn into incorrect commissions, financial losses or damaged relationships with affiliates. Building a custom solution means taking responsibility for everything: development time, infrastructure, maintenance, security and future changes. Vibe coding can speed up the first version, but it does not remove the complexity hidden behind a reliable tracking system. For prototypes and internal experiments, building your own tool can make perfect sense. But once software becomes responsible for tracking money and managing external partners, reliability, security and proven architecture matter much more. What Makes a Good Free Affiliate Tracking Platform? A good free affiliate tracking platform is not just about having a $0 price tag. The important question is: what are the limits, and how does the platform sustain itself? Look beyond the word “free” and check: Usage limits – How many clicks, conversions or affiliates can you manage before you need to upgrade? Hidden restrictions – Are important features locked behind a paid plan? Long-term viability – If a platform offers unlimited usage for free, understand how the infrastructure and development are funded. Scaling options – Make sure you can continue using the platform when your affiliate program grows. A free plan can be a great starting point, but reliable tracking infrastructure always has a cost somewhere. PalDock: Free Affiliate Marketing Software PalDock provides free access to the full affiliate marketing platform. Not a limited version with locked features or artificial restrictions. The difference is simple: the limit is not what features you can use, but how much value the platform generates for your business. You get access to all features from day one, including affiliate tracking, partner management, lead generation workflows and integrations. The platform is free until your affiliate activity generates revenue above a certain threshold. Unlike typical free plans, PalDock does not limit features. You get the same platform from day one. The limitation is based on the value generated, not on which features you can access. Affiliate tracking and partner management PalDock covers the core affiliate workflow: Click tracking – track affiliate traffic, sources and campaigns Conversion tracking – connect clicks with leads, sales or other desired actions Affiliate management – manage partners, access permissions and campaigns Commission tracking – define rules and monitor partner earnings Reporting – understand which partners and campaigns generate results Lead generation workflows Unlike many affiliate platforms focused only on referral links, PalDock is built also for lead-based businesses. You can: Create and manage lead forms – collect exactly the data your business needs with customizable fields and user flows Distribute leads to advertisers – connect multiple buyers and decide where each lead should go Track the full lead lifecycle – from affiliate click through lead submission, delivery and final result Manage partner and advertiser relationships – keep affiliates, buyers and campaigns connected in one place Build custom API integrations – connect virtually any advertiser, buyer or internal system with flexible data mapping and custom workflows The last part is where PalDock stands out. Affiliate and lead generation businesses rarely work with identical systems. Every advertiser has different API requirements, data formats and processes. Instead of relying only on pre-built integrations, PalDock gives you the flexibility to build and adapt connections for real-world scenarios. This makes PalDock suitable for industries where the conversion is not a direct purchase, but a qualified lead. Built to scale with your business PalDock is designed to remove the need for expensive upfront investment. You can start with a fully featured affiliate platform for free and scale as your affiliate channel grows. The pricing model follows the value created, not the number of features you are allowed to use. Who Should Use Free Affiliate Tracking Software? Free affiliate tracking software is a good fit for: Companies starting their first affiliate program – test whether affiliate marketing works before making a bigger investment Startups and smaller businesses – run campaigns without unnecessary upfront costs Teams validating new acquisition channels – measure results before scaling Companies with smaller affiliate programs – manage partners and conversions without enterprise-level complexity Once affiliate tracking becomes a major revenue channel, you may need more advanced features, higher limits and dedicated infrastructure. Choosing the Right Free Affiliate Tracking Software Free affiliate tracking software can be a great way to start, but the lowest price should not be the only thing you consider. A tracking platform is responsible for attributing revenue, calculating commissions and maintaining trust between you and your partners. The real cost usually appears when tracking breaks, conversions are missed or incorrect payouts create problems with affiliates. A free solution is valuable when it gives you enough functionality to test and grow, while still providing a reliable foundation for the future. PalDock takes a different approach by providing access to the full platform without limiting features. You can start for free, use the same tools available to larger programs and only pay when the platform generates enough value for your business. #### Harness full SEO potential from Redirects Harness full SEO potential from Redirects Have a flagship branded website driving traffic? Use it to its fullest by turning it into an SEO-boosting redirect hub. By using a 301 permanent redirect from affiliates to your domain and then a 302 temporary redirect to your advertisers, you harness all the SEO benefits from your affiliate links. Worried Google might flag them as affiliate links, given its skill for recognizing standard affiliate link structures? Design your own unique tracking parameters to fly under the radar.  #### How to: Affiliate Business Model How to: Affiliate Business Model Introduction Setting the right business model is a key step in managing an affiliate program. The business model defines how you reward your partners for their contributions and how you generate revenue from affiliate marketing. In this article, we will discuss the importance of a well-defined business model and provide useful tips to achieve it. Set Goals and Strategy When establishing your business model, it’s important to have clear goals and a strategy for your affiliate program. Consider whether you want to focus on generating sales, acquiring new customers, raising brand awareness, or other objectives. For example, if your goal is to generate sales, you might choose a pay-per-sale commission model. Choose the Right Commission Model The commission model determines how partners are rewarded for their contributions. Here are a few models to consider: Pay-per-sale (PPS): Partners earn a commission for each sale made through their links or codes. This is the most common model, suitable for e-commerce platforms. Pay-per-lead (PPL): Partners earn a commission for each lead generated, such as when a user fills out a form or registers on a website. Pay-per-click (PPC): Partners earn a commission for each click on their links that leads to your website. This model works well for sites with high traffic but lower conversion rates. Select the commission model that best fits your product, target audience, and program goals. Determine Commission Rates and Conditions Clearly define the commission rates you will offer to your partners. Consider standard rates in your industry and competitive factors. Ensure the commission is motivating for partners while still being sustainable for your business. Additionally, set conditions like minimum traffic requirements or specific goals that partners must meet to earn their commission. Consider Additional Bonuses and Incentives Beyond the base commission, you can motivate partners with extra bonuses and incentives. For example, offer higher commissions for reaching sales targets or bonuses for bringing new partners into the program. These incentives can boost motivation and encourage partners to be more active. Ensure Fair Tracking and Reporting A good business model needs a reliable system for tracking and reporting partner performance. Choose a trustworthy affiliate tracking software that allows you to monitor sales, conversions, and other relevant performance metrics. Make sure partners can access this information to track their performance and earnings. Regularly Review and Optimize Your business model should be flexible and adaptable. Regularly review your program’s performance and analyze whether the business model meets your expectations and goals. Consider making adjustments if opportunities for improvement arise. For instance, you might experiment with different commission rates, bonus structures, or additional incentives to optimize program performance. Conclusion Setting up the right business model is crucial for the success of your affiliate program. Carefully consider your commission model, commission rates, and other conditions. Regularly review and optimize your business model to reach the full potential of your affiliate program. #### How to: Building Long-Term Relationships with Partners How to: Building Long-Term Relationships with Partners Introduction Building and maintaining long-term relationships with your affiliate partners is crucial for the success of your affiliate program. Strong and trustworthy relationships enhance partnerships, increase productivity, and provide long-term value. In this article, we will focus on the importance of building lasting relationships with partners and provide useful tips on how to achieve this. Communication and Transparency Communication is the foundation of a strong partnership. Maintain regular and open communication with your partners. Share relevant information about your program, new products, or promotions. Be transparent about commissions, terms, and expectations. Active and effective communication builds trust and ensures that partners are fully informed about important changes and opportunities. Provide Necessary Support Support is key to your partners’ success. Provide them with the essential tools, materials, and training they need to effectively promote your product. Be available to answer questions, offer advice, and help solve problems. Ensure that partners have easy access to the necessary information and resources through a partner portal or other online interface. Recognition and Motivation Recognition and motivation are important for maintaining partner engagement and interest. Acknowledge and appreciate their achievements and contributions to the program. Offer awards for reaching goals or outstanding performance. Provide motivational bonuses or special rewards for top partners. Motivation and recognition strengthen bonds with partners and foster long-term loyalty. Collaborate on Strategy and Development Involve partners in the strategy and development process of your affiliate program. Ask for their feedback and ideas for improving the program. Work together on developing new initiatives and innovations. Partnership is a two-way street, so it’s important to listen to partners, consider their suggestions, and collaboratively work on program development. Provide Benefits and Educational Opportunities Add value for partners by offering exclusive benefits and educational opportunities. This may include access to exclusive offers, production materials, or training in affiliate marketing. By providing partners with additional benefits and skills, you show your commitment to their growth and success. Regularly Evaluate and Update the Program Regularly assess and update your affiliate program based on feedback and results. Analyze the program’s success and effectiveness. Identify improvement opportunities and adapt the program to meet partners’ needs and expectations. Keep the program fresh and competitive through regular innovations and enhancements. Conclusion Building long-term relationships with partners requires an active and ongoing approach. Maintain open communication, provide necessary support, recognize partner achievements, involve them in the strategy and development of the program, and offer benefits and educational opportunities. Regularly evaluate and update the program based on feedback and results. By doing so, you will establish strong, mutually beneficial partnerships that lead to long-term success for your affiliate program. #### How to: Challenges and Solutions in Managing Affiliate Partners How to: Challenges and Solutions in Managing Affiliate Partners Introduction Managing affiliate partners can be a challenging task with various obstacles to overcome. Effectively addressing these challenges is crucial for the successful management of your affiliate program and maximizing partner performance. In this article, we will focus on some of the main challenges you may face when managing affiliate partners and provide useful tips and solutions to deal with them. Recruitment and Selection of the Right Partners Challenge: Finding suitable and quality partners can be difficult, especially in a competitive environment. Choosing the right partners is key to achieving long-term collaboration and program performance. Solution: Set clear criteria for selecting partners. Conduct thorough research on potential partners and their reputation. Consider their relevant experience, audience, and past performance. Utilize affiliate networks or platforms to help identify quality partners and streamline the recruitment process. Communication and Support for Partners Challenge: Maintaining effective communication with partners and providing necessary support can be challenging, especially when managing a large number of partners. Solution: Establish a clear communication channel for partners, such as email, online chat, or a partner portal. Ensure quick and regular responses to their questions and requests. Provide ongoing support through training, webinars, a FAQ section, or a partner forum. Regular contact and transparent communication help maintain strong relationships and increase partner engagement. Monitoring and Managing Partner Performance Challenge: Tracking and managing the performance of many partners can be time-consuming and difficult. Identifying top and low performers and taking appropriate actions is essential for program optimization. Solution: Use affiliate tracking software that allows easy monitoring and analysis of partner performance. Define key performance indicators (KPIs) and track them regularly. Identify top performers and reward them while focusing on partners who are underperforming, offering them support and advice for improvement. Regularly review and update the program based on partner performance for success. Competition and Fraud Protection Challenge: In a competitive environment, keeping partners motivated and protecting the program from fraud, such as fake clicks or unfair practices, can be difficult. Solution: Establish rules and conditions for the program that prohibit unethical practices. Monitor traffic and watch for unusual patterns that could indicate fraud. Collaborate with trustworthy affiliate networks or technology partners that offer fraud protection tools. Maintain open communication with partners regarding rules and the consequences of unethical behavior. Innovation and Maintaining Motivation Challenge: Keeping partners motivated and engaged over the long term can be challenging, especially if the program stagnates and does not present new opportunities. Solution: Be a pioneer in innovation and create new opportunities for partners. Introduce new products, special offers, or contests that encourage partners to be active. Keep the program fresh and interesting, and regularly communicate updates and improvements. Conclusion Managing affiliate partners presents its challenges, but with the right practices and solutions, success is achievable. Recruit and select the right partners, maintain effective communication and support, monitor and manage partner performance, protect the program from fraud, and keep motivation high through innovation and new opportunities. By doing this, you will have the right tools and practices for successfully managing and growing your affiliate program. #### How to: Choosing Affiliate Partners How to: Choosing Affiliate Partners Introduction Choosing the right affiliate partners is a crucial factor for the success of your affiliate program. Quality partners not only drive increased traffic and sales but also strengthen your brand and contribute to long-term growth. In this article, we will focus on the importance of selecting the right affiliate partners and provide useful tips on how to do it effectively. Identify Your Target Audience and Relevant Partners Start by thoroughly analyzing your target audience. Determine who your ideal customers are, their interests, demographics, and preferred platforms. Then, look for partners who already reach this audience. Explore social media, blogs, websites, and forums popular among your target group. Create Selection Criteria for Partners Define criteria that will help you choose the right partners. Consider factors such as the quality of their content, the reach of their audience, their engagement within their community, and the relevance of their content to your product or service. You should also take into account their reputation, feedback from their visitors, and previous experiences with affiliate marketing. Conduct a Thorough Analysis of Partners Examine the online presence of potential partners. Analyze their websites, social media, and other platforms they use. Assess the quality of their content, website design, audience interaction, and engagement in conversations. Also, look at their ratings, references, and results achieved in affiliate marketing. Reach Out and Evaluate Potential Partners Contact potential partners via email, website forms, or social media. Introduce them to your affiliate program and highlight its benefits. Invite them to join the program and share their ideas for collaboration. Inquire about their interest, their vision for collaboration, and their ability to generate traffic. Set Terms Once you have identified potential partners who meet your criteria, it’s time to establish contractual agreements. Contracts should clearly define the responsibilities of both parties, the commission structure, the duration of the partnership, and other important terms. Ensure that the agreements protect your interests while being fair and mutually beneficial. Maintain Regular Communication and Support Regular communication and support are key to maintaining good relationships with partners. After agreements are in place, keep in touch with partners through emails, conferences, or video calls. Provide them with updates on news, marketing materials, and support for their activities. Be open to their feedback and involve them in the growth and development of the affiliate program. Conclusion Choosing the right affiliate partners requires careful analysis, evaluation, and communication. Follow the steps outlined above and don’t hesitate to seek out, contact, and evaluate partners. With careful selection and quality partners, you can achieve long-term success in your affiliate program. #### How to: Choosing the Right Affiliate marketing Tool How to: Choosing the Right Affiliate marketing Tool Introduction Proper measurement in affiliate marketing and lead generation is key to achieving success in your marketing campaigns. Choosing the right measurement tool and setting it up correctly allows you to track partner performance, analyze data, identify effective strategies, and adjust your campaigns for maximum impact. Factors to Consider When Choosing a Tool When selecting a measurement tool for affiliate marketing, consider several important factors. These will help you choose a tool that meets your business needs and allows you to measure and analyze your affiliate campaigns and lead generation effectively. Features: First, think about what features you need from the measurement tool. This might include conversion tracking, identifying individual partners, creating discount codes, or managing affiliate links. Make sure the tool meets your requirements and allows you to track key metrics. User Interface: A user-friendly and intuitive interface is crucial for effectively using the measurement tool. Check if the interface is clear, easy to navigate, and provides the necessary information and real-time analysis. Flexibility and Scalability: Consider the tool’s flexibility and ability to grow with your business. Ensure that it allows for adding new features and modules as you need them in the future. Functional Requirements and Business Needs Every business has specific functional requirements and needs in affiliate marketing. Before choosing a measurement tool, clearly define these requirements. Consider the following factors: Campaign Types: Ensure the tool supports the types of campaigns you plan to run, such as commission sales, conversion tracking, or social media post tracking. Tracking and Analysis: Confirm that the tool offers sufficient tracking and analysis options for your affiliate campaigns and lead generation. Think about which metrics and statistics you need to monitor and what analyses will help you optimize and make decisions. Integration with Other Tools: If you are already using other tools, like a CRM system or email marketing tool, check if the measurement tool can integrate with them. This will give you better visibility and a comprehensive view of your marketing activities. Comparing Available Tools There are several measurement tools available for affiliate marketing. To make the right choice, it’s important to compare these tools and find one that best meets your needs. Assess Features: Look at the features offered by different measurement tools. Compare their capabilities for conversion tracking, providing analysis and reports, managing partners, and other important functions. References and Reviews: Read reviews and experiences from other users of the measurement tools. Find out how well the tool works in practice, its reliability, and whether it meets user expectations. Pricing and Benefits Price is an important factor when choosing a measurement tool for affiliate marketing. Consider whether the benefits and features of the tool are worth its cost. Ensure that the selected tool meets your requirements and fits your budget. Integration with Existing Technologies If you already use other technologies and tools in your marketing stack, consider how the measurement tool will integrate with these existing systems. Check if the tool can integrate with your CRM, web analytics, email marketing, or other essential tools. This will provide you with overall visibility and efficiency in tracking and managing your affiliate campaigns. Data Security and Privacy Protection Lastly, data security and privacy protection are crucial factors. Find out how the tool ensures the security of your data and whether it complies with relevant laws and regulations regarding data protection. Conclusion Choosing the right measurement tool is essential for successfully measuring affiliate marketing and lead generation. Carefully consider key factors, functional requirements, available tools, pricing, integration with existing technologies, and data protection to select a tool that meets your needs and contributes to the success of your campaigns and quality lead generation. #### How to: Defining Goals and Expectations Introduction Defining goals and expectations is a fundamental step in managing an affiliate program. Setting clear goals and understanding what you want to achieve through the program is key to its success and performance measurement. In this article, we will discuss the importance of defining goals and expectations and provide useful tips on how to do it effectively. Analyze and Understand Your Business Before defining the goals of your affiliate program, it’s important to have a clear understanding of your business. Conduct a thorough analysis of your products or services, target audience, competition, and the market you operate in. Understanding your business will help you determine how the affiliate program can contribute to its growth and success. Specify Measurable Goals The goals of your affiliate program should be specific, measurable, achievable, relevant, and time-bound (SMART). For example, you might aim to increase sales by a certain percentage, acquire new customers, improve conversion rates, or raise brand awareness. Measurable goals will allow you to track program performance and evaluate its success. Focus on Strategic Priorities Concentrate on the key priorities of your business and consider how the affiliate program can help achieve them. For instance, if you want to gain a larger market share, a goal for your affiliate program might be to acquire new partners who can reach your target audience. Identifying strategic priorities will help you focus on the key areas where you want to develop the program. Determine the Expected Benefits for Partners In addition to defining your goals, it’s also important to consider what benefits you will offer to affiliate partners. Think about how the program can help partners generate income, acquire new customers, or provide them with additional advantages, such as enhanced support or exclusive access to products. Clearly communicate these benefits to partners to motivate them to join the program. Monitor and Evaluate Program Performance One of the most important aspects of defining goals and expectations is the ability to monitor and evaluate the program’s performance. Ensure you have the right tools and metrics to track key performance indicators, such as the number of conversions, order value, or return on investment (ROI). Regularly analyze the data and make adjustments to the program based on your insights. Conclusion Defining goals and expectations is the cornerstone of successful affiliate program management. Careful planning and goal specification will help you measure and evaluate program performance, optimize strategy, and ensure long-term growth and success. Don’t forget to regularly communicate with partners about the goals and expectations of the program to build strong partnerships and mutually beneficial relationships. PalDock Has Your Back! Whether you’re a publisher, affiliate, webmaster, influencer, advertiser or network, PalDock helps you grow your business. With cutting-edge tools and innovative solutions, we ensure you’re ahead of the competition. Try for Free Resources [1] Wikipedia. Article Name. In: Wikipedia.cz [online]. Available on: https://cs.wikipedia.org #### How to: Motivating and Rewarding Partners Introduction Motivating and rewarding your affiliate partners is essential for their engagement, activity, and long-term collaboration. Proper motivation and rewards can encourage your partners to put in maximum effort in promoting your product, leading to increased sales and the success of your affiliate program. In this article, we will focus on the importance of motivating and rewarding partners and provide useful tips on how to achieve this. Establish a Clear Commission Structure Start by establishing a clear commission structure for your partners. Define the amount or percentage of commission they will receive for each sale or other goals achieved. Ensure that the commission structure is transparent, easy to understand, and motivating for partners. Differentiate commission levels based on sales achievements or performance, which can encourage partners to increase their efforts. Provide Bonuses for Achieving Goals Motivate your partners to reach set goals by offering bonuses for their successes. For example, you can provide an extra commission for reaching a certain sales volume, number of new customers, or other key performance indicators. These bonuses can serve as an additional motivation for partners. Make sure that the goals are realistic, achievable, and appropriately rewarded. Consider Higher Commissions for Top Partners Implement a reward strategy for top partners by offering them higher commissions or exclusive benefits. This will motivate high-performing partners to continue their efforts and remain active promoters of your product. Ensure these benefits are clearly defined and available to deserving partners. These might include higher commission rates, access to exclusive offers, faster commission payouts, or better support from your team. See our related article Release notes 2026/08/14 This was a big one. We went through roughly 200 pages of our knowledge base and rewrote the whole thing. Clearer structure, consistent terminology, and… Learn more: Release notes 2026/08/14 Organize Competitions and Incentives Host competitions and incentives for your partners to encourage higher activity levels. For example, you could announce a monthly contest for the highest sales or the most new customers generated. Provide attractive prizes or bonuses for contest winners. Competitions and incentives create healthy competition among partners and boost their engagement. You can also consider regular motivation programs, such as rewarding partners for long-term collaboration or outstanding performance. Provide Marketing Support Motivate your partners by providing marketing support. Offer ready-made marketing materials, such as images, videos, text links, or banner ads. Allow them access to these materials through a partner portal so they can easily use them in their campaigns. Providing quality marketing resources enhances the value of collaboration and encourages partners to be active. Additionally, you can offer training and consultations to help them improve their affiliate marketing skills. Recognition and Communication Recognize and communicate your partners’ successes. Share important data about their performance and highlight their contributions. Create a community for partners to share their successes, experiences, and tips. Recognition and communication strengthen partnerships and increase motivation for further growth. Regularly communicate with partners through newsletters, personal meetings, or online forums to ensure they feel connected to your company and have direct access to relevant information. Conclusion Motivating and rewarding partners are key to the success of your affiliate program. Establish a clear commission structure, provide bonuses for achieving goals, consider higher commissions for top partners, organize competitions and incentives, offer marketing support, recognize partner successes, and maintain regular communication. By doing so, you will have motivated and engaged partners contributing to the growth and success of your affiliate program. #### How to: Optimizing Affiliate Program How to: Optimizing Affiliate Program Introduction Monitoring and optimizing your affiliate program is crucial for achieving maximum success and performance. By regularly tracking and analyzing your program’s performance, you can identify strengths, uncover improvement opportunities, and ensure effective resource utilization. In this article, we will focus on the importance of monitoring and optimizing your affiliate program and provide useful tips on how to do this. Define Key Performance Indicators (KPIs) Before you start monitoring and optimizing, it’s important to establish key performance indicators (KPIs) that will help you measure your program’s success. KPIs should be specific, measurable, achievable, relevant, and time-bound. For example, you might track the number of new registered partners, sales generated through affiliate links, conversion rates, and the average order value. Utilize Affiliate Tracking Software To effectively monitor your affiliate program’s performance, it’s essential to use reliable affiliate tracking software. This software will allow you to track and analyze commissions, sales, conversions, and other important metrics. Choose a software that is compatible with your business model and allows accurate tracking of each partner’s contributions. Monitor and Analyze Partner Performance Regularly track and analyze your partners’ performance. Identify which partners generate the most sales or the highest quality traffic. Recognize their strengths and support their efforts. At the same time, focus on partners with weaker performance and consider how you can motivate or provide them with the necessary support. Communicate with Partners Maintain regular communication with your partners. Share important information, such as product updates or promotions they can promote. Provide feedback on their performance and offer advice and tips for improvement. Active communication helps build strong relationships and encourages partner engagement in the program. Test and Optimize Strategies and Materials Experiment with different strategies and marketing materials. For instance, try various types of banners, text links, or content marketing strategies. Monitor the results to identify which strategies and materials perform best. Optimize your approaches based on these insights and adjust your marketing materials to maximize their effectiveness. Regularly Review and Update the Program Continuously review the performance and effectiveness of your affiliate program. Analyze KPIs, track trends, and discover improvement opportunities. Based on this information, update your strategies, processes, and program conditions. Ongoing optimization will help you maintain competitiveness and achieve long-term success. Conclusion Monitoring and optimizing your affiliate program are essential for reaching its full potential. Define key performance indicators, utilize affiliate tracking software, monitor and analyze partner performance, maintain regular communication, test and optimize strategies and materials, and regularly review and update your program. By doing this, you will have control over your affiliate program’s performance and be able to achieve lasting success. #### How to: Providing Marketing Materials and Tools How to: Providing Marketing Materials and Tools Introduction Providing the right marketing materials and tools for your affiliate partners is critical for their success in promoting your product or service. Effectively making these resources available can boost their motivation, strengthen your brand, and contribute to the long-term growth of your affiliate program. In this article, we will focus on the importance of providing marketing materials and tools, along with useful tips on how to achieve this. Identify Partner Needs When setting up your affiliate program, it’s important to have clear goals and a strategy. Consider whether you want to focus on generating sales, acquiring new customers, raising brand awareness, or other objectives. For example, if your goal is to generate sales, you might choose a pay-per-sale commission model. Create Quality Marketing Materials Start by identifying what marketing materials and tools would be most helpful for your partners. Communicate with them through surveys, conversations, or polls to find out which materials would best support their efforts in promoting your product. Ask about their preferences, such as images, videos, banner ads, text links, reviews, etc. Gather their feedback to better understand their needs. Provide Materials in a Partner Portal Create a partner portal that allows your partners easy access to all marketing materials and tools. This could be a dedicated section on your website or a separate platform where partners can log in and download materials. Ensure that the portal is intuitive, user-friendly, and secure so that partners can easily access everything they need. Offer Training and Support Teach partners how to effectively use the marketing materials and tools provided. Organize training sessions, workshops, or webinars to show them how to implement these resources into their campaigns. Also, provide ongoing support by answering their questions, offering advice, and helping them maximize the potential of the materials. Make sure partners have the knowledge and skills needed for successful promotion. Keep Marketing Materials Up to Date Regularly update and maintain your marketing materials to keep them current. Ensure they reflect the latest changes in your product, brand, or market. Update images, videos, product descriptions, and other relevant materials regularly. Provide partners with access to updated versions and inform them about any changes that may affect their promotions. Keeping materials fresh ensures that partners always have relevant resources for their campaigns. Gather Feedback and Analyze Performance Actively seek feedback from partners about the marketing materials and tools you provide. Ask for their opinions, ratings, and suggestions. Find out which materials and tools are most effective for them and what could be improved. Also, analyze the performance of these materials, tracking which ones yield the best results and which may need optimization. Conclusion Providing the right marketing materials and tools is essential for the success of your affiliate program. Make sure to identify partner needs, create quality materials, provide access through a partner portal, and offer training and support. Regularly update materials, gather feedback, and analyze performance to optimize your marketing approach and achieve maximum success for your affiliate program. #### iFrame forms iFrame forms Legend: Affiliate partner = Marketer or a Company delivering traffic for commissions Advertiser = Lead Generation company or Provider of some service buying traffic Lead = customer’s data usually from filled form iFrame form = Form embedded on website of affiliate partner under control of the Advertiser for collecting customer’s data When the link redirection is not enough for your affiliate’s or advertiser’s needs, you will soon start dealing with API and custom or iframe forms. API for delivering customers data Where API is a method of delivering the customer data to the advertiser, the form is a way of collecting those data from the user. And as with most of the things where the user is involved, this part is prone to error – technical, UX or human. Form for collecting customers data Forms need to be done flawlessly so the process is efficient – your money is at stake. That is why we have created a robust iframe form builder for Paldock. So you or your affiliate does not have to worry, because this difficult technological part is already done by us and can be customized for your needs.  What you need to do is to define what fields do you want to have in your iframe in how many steps and in what order. Then you will set predefined field validation or create your own. Later on you need to map the fields from iframe to your advertisers based on their API integration requirements.  Paldock will generate the iframe which can then be customized and placed to yours or affiliate partner websites on the internet. From that moment you start to collect the customer’s data as leads, which can be sold in several ways – more on this in the chapter Lead routing and distribution. Data enrichment The biggest benefit is that YOU collect the data and you are the owner (and you can allow the same for your affiliate partners). In this marketing age, there are dozens of ways how these data can support your business further and provide you competitive advantage.  Pro tip: if you are in an industry, where the customer might get rejected by the advertiser (if you are selling the leads exclusively to just one), you can use a feature called Alternative offer. That means, in situations where the main advertiser rejects the customer, you can either ask the customer for approval or sell the customer directly to an alternative advertiser. #### Invoicing Made Simple Invoicing Made Simple Receive invoices from your affiliate partners or let Paldock auto-generate them on their behalf. We’ve got the checks and balances in place to adjust their account balances accurately, ensuring seamless payments every time. Got internal rules about the number of invoicing partners? No worries. We can consolidate everything, making Paldock your single point of contact for invoicing. Networks can easily produce invoices for advertisers via Paldock and monitor their payment status. This is especially handy when affiliate partners must first wait for advertisers to settle with the network before their commissions get approved. #### Lead API Lead API Legend: Affiliate partner = Marketer or a Company delivering traffic for commissions Advertiser = Lead Generation company or Provider of some service buying traffic Lead = customer’s data usually from filled form iFrame form = Form embedded on website of affiliate partner under control of the Advertiser for collecting customer’s data The classic tracking link integration is a cooperation, where affiliate partners integrate the advertisers through link redirection with special parameters. However, there might be cases and industries, where that is not enough. At that moment, the API integration shines. API is basically a connection between your server and the server of the advertiser or affiliate partner. And in this connection the customer’s data flows. But how do they get there? And where do they go? How they get there API is just a connection for delivering the data, but it does not collect data. The data collection is done by custom form or iframe form. The single purpose of iframe form on the other hand, is only to collect data. So let’s imagine a situation where the customer is looking for some product or service. Once the customer is searching for some product, he might find some affiliate partner’s website and in the end be redirected to the website of the advertiser to get the product. That is classic tracking link integration. But the customer can also directly request for the specific product on the mentioned affiliate partner’s websites. The affiliate partner just needs to place there an iframe form, which will collect the customer’s data as a lead. You can read more about how to get this iframe form and what are the difficulties in our articles about iframe forms.  Where they go Once the iframe form is placed and running, it needs to send the data somewhere. And that is the moment where API integrations come in. You can either collect the data for yourself and send them through API to your system or you can send these data through API to others. For this purpose, we create in Paldock robust API documentation and an API standard for connecting iframes with your system and a system of other advertisers.  Summary Now you send the leads from your iframe form to your advertisers. Easy right? Well… there is more than meets the eye. And that is why Paldock is here. Thanks to Lead distribution you can choose the method how to sell those leads (yes, there are several ways) to get the best results. And as a bonus, there are already dozens of prepared API integrations. You don’t have to spend money on integrating them or on maintenance. We got that covered. #### Lead distribution and routing Lead distribution and routing Legend: Affiliate partner = Marketer or a Company delivering traffic for commissions Advertiser = Lead Generation company or Provider of some service buying traffic Lead = customer’s data usually from filled form API integration = method of sending lead Everyone knows that affiliate partners generate website traffic and redirect it to the website of an advertiser for commissions. In some industries, this link redirection is the only way how it’s done. But in industries such as Finance there is also another available method of delivering customers – sending Leads from custom forms or iframes forms through API. Meaning sending the lead (customers data) directly to the CRM of the advertiser without the need of the customer to visit the advertiser’s website.  This method of delivering customers opens doors to new, more efficient opportunities of generating traffic and as a result, creating competitive advantage. There are more approaches of how the traffic can be delivered through API and in this article I will describe the most common ones: Exclusive Distribution Non-Exclusive Distribution Exclusive Auction Distribution User-Centric Distribution¨ Exclusive Distribution Imagine you will fill an iframe form for a loan and an automated system will pick one provider (advertiser) for you. That is the Exclusive Distribution. The logic of choosing the right provider might be in either: customer’s data analysis and scoring, where the supplier (be it affiliate partner or lead generation company) is looking for the best fit or simply by offering the lead to the advertiser with the highest predefined commissions (either per sale or lead) for delivered customers. Where in this setup, the advertiser might have specified several commissions per a lead depending on the lead quality. Thus the advertiser distribution list might look like this: Important thing here is that the lead is offered to one advertiser at a time. Which means that the selling process takes longer, but it provides better control and security for the lead data. There is no input needed from the customer and everything is automatized, which means the customer has fewer places to drop off. But on the other hand, some customers might not welcome the automated pick and might prefer to pick themselves. Exclusive Auction Distribution We will stay in the Exclusive Distribution for a moment longer. Special case of Exclusive Distribution is Auction Distribution, where the lead is offered to ALL advertisers at once and the commission for the lead is not predefined, but is unique for each lead. Thus in realtime the Advertisers are bidding on the lead and the highest bid wins (there is only one round of bidding). However, this method requires a high technological level of the advertisers since they need to be able to do customer scoring within a few seconds or under a minute at max. Non-Exclusive Distribution In case of less technologically developed markets it might not be possible to offer the lead to one advertiser, because the advertiser is not capable of scoring the customer properly and the conversion from the lead to sale is low. Thus the commissions are low as a result. In this case, there is Non-Exclusive Distribution, in which the lead is offered to more advertisers at once depending on predefined filters and maybe a light scoring. In the end, more advertisers will be interested in the customer and the customer will be sold to all of them or part of them at the same time. User-Centric Distribution If you want to give more power to your users, there is User Centric Distribution. The users themselves choose where they want to be sold to.  The lead is offered to all advertisers at once and only the interested advertisers are shown. Users can then choose which offers to proceed with. The advantage of this approach is obviously the user experience of the users since they have more control over the whole process. Plus the user might be interested to proceed with more offers at the same time to increase the chances of approval or even to take several loans. The disadvantage is that the user has more opportunities to drop off. Summary And of course, there is a whole process behind this. Lead verification, filters for lead routing, redirect possibilities and more. But Paldock has it all including all Lead distribution types, so you can test what type suits your business the best. Once you will start to deal with distribution of the lead, new opportunities arise but also threats. The process and mainly the iframe form needs to be done flawlessly, so the users have fewer places to drop off. We got you covered. As a part of Paldock, there is also a robust iframe form builder so you or your affiliate does not have to worry. This difficult technological part is already done and can be customized for your needs. PRO TIP: Are you an advertiser and think this is not for you? Wrong! You can monetize your rejected leads with our Lead Distribution feature to get the most out of it, so you can buy more customers you want. #### Lead Distribution Software What is Lead Distribution Software Lead distribution software is a platform used to route and deliver leads to one or more lead buyers (advertisers) in real time. Instead of sending every lead to a single company, it lets you define multiple buyer channels, apply eligibility rules, and decide who should receive each lead based on your distribution logic and performance goals. The result is a controlled, auditable flow where every lead is either delivered and sold to a buyer, routed to the next eligible option, or ends with a clear final status. In modern lead generation operations, lead distribution software typically sits between lead intake and buyer delivery. It accepts leads from forms or partner APIs, filters out ineligible paths, validates and deduplicates data, enforces caps and pacing, and sends the lead to buyer endpoints using direct delivery, ping post, ping tree, auctions, or user choice flows. Because all decisions and responses are logged, teams can troubleshoot rejects, optimize revenue, and prove exactly what happened to each lead Lead Routing Has Two Meanings The term lead routing is used in two different contexts, which is why search results can look mixed. In CRM and sales workflows, lead routing usually means assigning inbound leads to the right sales rep, team, or territory so they can follow up and close the deal. The “destination” is an internal pipeline. In lead generation and lead buying workflows, lead routing means distributing leads to one or more lead buyers (advertisers) and delivering them via API as a sale. The “destination” is an external buyer endpoint, and the routing decision is driven by eligibility rules, caps, pricing, and performance outcomes. In here, lead routing refers to the second meaning: real time lead distribution for buying and selling leads. How a Lead Distribution Platform Works A lead distribution platform sits between lead intake and buyer delivery and runs a simple decision pipeline for every lead: Lead intake: the lead arrives from a form, partner, or API source. Filters: basic eligibility rules remove buyer channels that would clearly reject the lead. Validation: required fields and formats are checked so bad data does not reach buyers. Deduplication and suppression: duplicates are detected and blocked based on your rules and lookback window. Routing decision: the platform applies your distribution logic to choose the best buyer path (direct, ping post, ping tree, auction, or user choice). Delivery: the lead is sent to the buyer’s endpoint as the actual sale, with retries and fallbacks if needed. Outcome and lifecycle: the buyer response or callback confirms the final status, and the lead is marked accordingly. Delivery logs and reporting: every step is stored so you can audit outcomes, debug rejects, and optimize revenue and acceptance rates. This is why lead distribution platforms are more than simple forwarding tools: they combine routing logic, reliability controls, and traceability so lead buying and selling can scale without manual firefighting. Delivery Models Inside Lead Distribution Lead distribution software can deliver leads in a few standard ways. The core difference is whether you send the lead straight to one buyer, or first “offer” it to multiple buyers and then decide where the sale happens. Direct delivery to one buyer The simplest model is sending the full lead directly to a single buyer endpoint. This works well when you have one buyer, fixed terms, and clear acceptance rules, and you mainly need validation, deduplication, caps, and reliable delivery. Ping Post and Ping Tree distribution In Ping Post flows, ping is optional and post is required. The platform can first ping one or more buyers to confirm eligibility, capacity, or pricing, and only then post the full lead to the winning channel. A Ping Tree builds on this by grouping multiple buyer channels and applying distribution logic like exclusive routing, non exclusive distribution, auctions, or user choice to decide who gets each lead. If you want the full mechanics, see the dedicated Ping Tree and Ping Post guide. Auctions and marketplace style flows In auction flows, multiple buyers respond with bids and the platform posts the lead to the highest bid based on your rules. In marketplace style flows, the platform can show the successful options to the user and post the lead only to the option the user selects. These models are common when buyers value leads differently and you want either price competition or user driven selection while keeping the process auditable. Software for Lead Sellers and Buyers A lead distribution platform is often described as buy and sell leads software because it supports both sides of the transaction: sellers who generate and monetize leads, and buyers who purchase and process them. The same routing engine is used, but the goals and controls look different depending on which side you operate. For lead sellers and brokers Sellers use lead distribution software to maximize revenue and keep operations stable while sending leads to multiple buyers. That usually means setting clear eligibility rules per buyer, selecting the best outcome per lead, enforcing caps and pacing, preventing duplicates, and keeping full delivery logs for disputes and reconciliation. Sellers also rely on performance reporting to understand which sources produce profitable leads and which buyers deliver the best effective price and acceptance rate. For lead buyers: lead management software in practice For lead buyers, lead distribution software functions as lead management software focused on purchase quality and fulfillment. Buyers need tight control over what they receive, including required fields, validation rules, geographic and product constraints, consent markers, caps and pacing, and clear rejection reasons when a lead does not match. They also benefit from lifecycle tracking and feedback loops so they can measure lead outcomes, improve acceptance criteria, and align pricing with real performance. What to Look For in Lead Distribution Software Because lead distribution sits directly on the revenue path, the best platforms combine routing logic, reliability, and transparency in one system. When evaluating a lead distribution platform or lead routing software, these are the capabilities that matter in practice: Multiple distribution logics: support for exclusive routing, non exclusive distribution, auctions, and user choice, with the flexibility to apply different logic per buyer channel. Fast buyer integrations: field mapping, payload transforms, authentication and request signing, and callback handling, so onboarding a new buyer does not become a custom engineering project. Filters, validation, and deduplication: to block guaranteed rejects and duplicates before they create latency and waste buyer capacity. Caps, pacing, and prioritization: controls to respect buyer limits and distribute volume intentionally over time, not just “first come first served.” Reliability controls: strict timeouts, retries where appropriate, idempotency to prevent double posts, and fallbacks when a buyer endpoint is slow or down. Auditability and traceability: delivery logs, routing traces, timestamps, and rejection reasons, so every outcome can be explained and reconciled. Reporting tied to revenue: acceptance rate, effective price, latency, buyer performance, source performance, and outcomes, so optimization is based on profit, not guesses. If a platform is missing transparency or reliability, it may still “route” leads, but it will not scale when volumes grow, buyers become stricter, or integrations start failing under load. PalDock as a Lead Distribution Platform PalDock is built for real time lead buying and selling workflows, combining lead distribution software and lead routing platform capabilities with native support for Ping Post, ping trees, auctions, and choice flows. It lets teams intake leads from forms or APIs, apply filters, validation, and deduplication, route each lead using the right distribution logic, and deliver it to advertiser endpoints with clear lifecycle statuses and full delivery logs. The key advantage is speed of change: PalDock’s visual no code integration layer supports field mapping, payload transformations, authentication and request signing, retries, and callbacks, so you can onboard new buyers and adjust routing rules without turning every update into an engineering project. #### Link tracking Link tracking Legend: Affiliate partner = Marketer or a Company delivering traffic for commissions Advertiser = Lead Generation company or Provider of some service buying traffic Horst Fuchs = famous teleshopping star from Germany I know, I know. Another link tracking software. Yes, there are dozens of link tracking softwares, but we are unique! ???? Paldock combines the advantages of link tracking with lead generation. Thus if you are in an industry where the lead generation exists, you would sooner or later do it. Be prepared for it and use a scalable future-proof software which not only supports link tracking, but also Lead generation. Such as Paldock. And as Horst Fuchs says: “That’s not all!”. The Paldock already comes with affiliate partner’s support. Required intro Just to not get too ahead of us, let’s start with basics. Link tracking means that you use special tagged links for your campaigns such as www.example.com?id={visitor_id} This link will generate the ID for each visitor and if this visitor will convert or do some required action, you (if you are an advertiser) or the advertiser (if you are an affiliate) will inform the software about this. Thanks to this you get realtime information about what happens to the visitor including the possible earned commission for those actions. Iframe Form so you can collect the customer’s data If you are an affiliate partner and you want to collect the customers data directly and not only send the customers to advertisers website, you can do it thanks to your robust iframe form builder. More about that in the iframe form article. If you are an advertiser (or affiliate network) and want to provide your affiliate partners with an iframe connected to your system, you can again thanks to our iframe form builder. API integrations for lead generation But that data from the iframe form needs to go somewhere somehow. And that is where the API integrations come in. We created a robust API standard for receiving and sending the leads with advanced logic of lead distribution. Summary In other words, Paldock is prepared for your future needs in terms of affiliate partners or lead generation. Can you say it for your current tracking solution? #### Optimize your Paid Ads thanks to Click tracking Optimize your Paid Ads thanks to Click tracking Running Paid Ads for your site? Wondering which exact clicks lead to conversions on the advertiser’s end? With our custom tracking, you can tag each click from your ads (using tools like Google Tag Manager) and attach it to your affiliate links. So when a sale or conversion occurs, you’ll pinpoint which exact click made it happen. Allowing you to automatically optimize your ads because Paldock can directly send this data to your Ad system via a server-to-server postback. #### Ping tree software and ping (pick) post distribution What is a Ping Tree A ping tree (sometimes written as pingtree) is a lead distribution method used to sell a single lead to the right advertiser in real time. Instead of sending every lead to one buyer, a ping tree lets you offer the same lead to multiple advertisers and decide who gets it based on the distribution logic you choose. Think of it as a smart router for lead monetization. You control which advertisers can receive the lead, what rules must be met, and how the winner is selected. The outcome is simple: the lead is either sold and delivered to an advertiser, or it continues through the routing until a valid sale happens, or the flow ends with a clear status. Ping trees are most common in markets where multiple advertisers buy the same type of lead, such as insurance, lending, home services, solar, telecom, and education. They are used by lead brokers, affiliate networks, performance teams, and lead sellers who need to maximize revenue while keeping acceptance rates, caps, and buyer requirements under control. Ping tree is not CRM lead routing (assigning sales leads to sales reps). It is real-time lead distribution to advertisers, designed for lead buying and selling workflows. Ping Post Explained: The Ping Post Basis A ping tree runs on a simple selling mechanism called Ping Post. The rule is straightforward: Ping is optional. Post is required. Ping is the “offer” phase. Post is the “sale and delivery” phase. In practice, Ping Post means you can first ask one or more advertisers whether they want the lead, and only if they respond positively do you send the full lead payload. This is useful because many buyers have strict rules, caps, and quality requirements, and you do not want to transmit full personal data to a buyer who is not eligible to buy the lead right now. Ping vs Post: what each step does Ping is a lightweight request that offers the lead. It typically contains only the minimum data needed to evaluate the lead, for example: product or vertical identifier location signals (country, region, postal code) basic qualifiers (age range, vehicle type, property type, etc.) traffic metadata (source, partner id, click id, timestamps) It usually excludes contact details so the advertiser cannot reject the lead and still process it outside the broker. The Ping response tells you whether the buyer is willing to purchase the lead right now. Depending on the setup, it may include: accept or reject decision a price or bid amount rejection reason codes cap or availability flags Post is the actual sale. This is where you send the complete lead payload to the selected advertiser endpoint. The post request usually includes: full user-provided data (including contact details) routing context (which channel won, what logic was used, bid or price, timestamps) identifiers used for reconciliation and reporting After the post is sent, the buyer returns the final status, accepted or rejected. With an accepted ping, a rejection on post should be uncommon and usually points to validation or consistency issues. Why Ping exists Ping is not “extra complexity for fun”. It exists because it improves control and revenue in real lead selling operations: Caps and eligibility: you avoid posting to buyers that are capped or will reject the lead Speed and reliability: you can pick a working buyer when one endpoint is slow or down Privacy and compliance: you can avoid sharing full personal data until a buyer commits Monetization: you can compare multiple buyers and choose the best outcome In short, Ping Post is the mechanism that makes a ping tree possible: you can offer the lead, learn who is willing to buy, then complete the sale with a post to the winning channel. Filters Before any ping happens, most ping tree setups run filters to avoid wasting time and requests on channels that would reject the lead anyway. These filters evaluate the incoming lead against each channel’s basic requirements such as country or region, product eligibility, required attributes, device or traffic constraints, or any other rule you define. Each ping or post request adds latency while the user is waiting on a loading screen. Distribution Logics in a Ping Tree A ping tree always follows the same foundation: Ping is optional, Post is required. What changes is the distribution logic, meaning how the system decides which advertiser gets the lead, and what happens if multiple advertisers are eligible at the same time. The four most common logics are Exclusive, Non-Exclusive, Auction, and Choice. Exclusive In Exclusive distribution, advertisers are evaluated one at a time. Typically, the ping tree starts with the channel that is expected to earn the most, based on your performance model (for example the highest expected profit per lead, not necessarily the highest raw commission). If the first advertiser accepts the lead, the flow ends and the lead is posted to that channel. If the advertiser rejects or does not respond in time, the ping tree continues to the next channel until a successful sale happens or the list is exhausted. Non Exclusive In Non Exclusive distribution, the lead is offered to multiple advertisers at the same time, regardless of ordering in the ping tree. Multiple advertisers can accept the same lead simultaneously. This logic is useful when you want maximum reach or parallel qualification, and when your user experience supports showing multiple successful results instead of forcing a single winner. Auction In Auction distribution, the lead is offered to multiple advertisers (ping) and each returns a price or bid. The ping tree then selects the winner using auction rules, most commonly the highest bid, and posts the full lead to the winning channel. Auction logic is often used when buyers value each lead differently and price competition is strong enough to increase your effective revenue per lead. Choice (User Pick) In Choice distribution, the lead is offered to multiple advertisers (ping), and the user sees the channels that successfully responded on a Choice page. The user then chooses where they want to apply, and the lead is posted only to the selected channel or channels. This is effectively the Ping Pick Post pattern, because the “pick” is performed by the user, not by price or routing priority. Real Time Lead Distribution Real-time lead distribution is the process of deciding where a lead should go immediately after the user submits it, while they are still waiting for the next screen. A ping tree does this by running a short decision pipeline that filters out impossible channels, offers the lead to eligible buyers, and then completes the sale with a post to the final channel. A typical pipeline looks like this: Lead is created from a form submission or an API intake. Filters run to remove channels that would obviously reject the lead. Validation and deduplication check that the data is usable and not a repeat. Eligible channels are pinged based on the chosen distribution logic (exclusive, non exclusive, auction, or choice). A winner is selected by the system (exclusive or auction) or by the user (choice). The lead is posted to the winning or selected channel as the actual sale. The final status is confirmed via the post response or a callback, and the lead lifecycle is updated. Delivery logs are stored so you can see exactly what happened, including rejects, timeouts, retries, and outcomes. Because every request adds latency, real time lead distribution is always a balance between maximizing revenue (pinging more buyers, running auctions, adding fallbacks) and minimizing user wait time (filtering early, using tight timeouts, and avoiding unnecessary pings). Common Failure Modes (and Fixes) Ping trees are simple in concept, but in production the same problems show up repeatedly. The good news is that most issues have clear, predictable fixes once you know what to look for. High reject rate If many pings or posts come back rejected, it usually means the lead does not match buyer requirements, required fields are missing, consent signals are incomplete, or your filters are too loose. Tighten filters, validate required fields earlier, and make sure each buyer’s spec is reflected in your routing rules so ineligible leads never reach the ping stage. Timeouts and buyer outages Slow buyer endpoints create long loading screens and lost sales. Use strict timeouts, retries only where they make sense, and always configure fallbacks so a single failing buyer does not block the whole flow. Monitor response times per channel and temporarily downgrade or disable unstable endpoints. Duplicates and disputes Duplicate leads waste money and damage buyer trust. Add deduplication windows and suppression lists using stable identifiers such as phone, email, or external ids, and keep the logic consistent across all channels. If buyers also run their own dedupe, align your rules so you do not send leads that are guaranteed to be rejected. “Where did my lead go” If you cannot explain why a lead was rejected or where it was sold, you are missing traceability. Store delivery logs for each ping and post, capture rejection reasons, timestamps, and routing decisions, and keep a clear lead lifecycle so every lead has an auditable history. Choosing Ping Tree Software When people search for ping tree software, they are usually trying to solve one thing: reliably selling leads to multiple advertisers in real time without losing money to rejects, timeouts, or messy operations. A good ping tree platform is not just “routing”, it must combine distribution logic, integration tooling, and full traceability so you can scale without guessing. Here is what to look for: Ping Post API support: the ability to run ping and post requests with flexible payloads, headers, and authentication. All core distribution logics: Exclusive, Non Exclusive, Auction, and Choice, plus the ability to combine them when needed. Filters, validation, and deduplication: so ineligible or duplicate leads are never sent to buyers and do not waste user time on a loading screen. Caps, pacing, and prioritization: to respect buyer limits and control how volume is distributed over time. Reliability controls: strict timeouts, retries, idempotency, and fallbacks so a single endpoint cannot break your flow. Delivery logs and rejection reasons: so every lead has a full audit trail showing what was pinged, what responded, what was posted, and why. Reporting tied to revenue: acceptance rate, effective price, buyer performance, latency, and outcomes, so you can optimize toward profit, not vanity metrics. If you operate more like a marketplace, you may also need buyer management, invoicing, and payout workflows, but the foundation is always the same: fast real time distribution, accurate outcomes, and complete transparency. PalDock was built specifically for this lead distribution use case. It supports Ping Post execution, Exclusive, Non Exclusive, Auction, and Choice flows in a single ping tree, and adds a visual no code integration layer for payload mapping, signing, retries, and callbacks, so you can connect buyer APIs and adjust routing rules quickly without turning every change into an engineering project. Learn more about how we handle ping tree in Paldock. What is a ping tree A ping tree (pingtree) is a real time lead distribution method that lets you offer one lead to multiple advertisers and decide who gets it using rules such as exclusive routing, non exclusive distribution, auction bidding, or user choice. Ping tree vs ping post: what’s the difference Ping post is the delivery method. Ping tree is the system that uses ping post to choose the best advertiser when multiple buyers are available What is ping post API Ping post API is the set of requests used to sell a lead in two steps: a ping request to check eligibility or pricing, followed by a post request that delivers the full lead to the winning or selected advertiser. What is real time lead distribution Real time lead distribution is the process of routing and selling a lead immediately after it is created, while the user is still waiting for the next screen, using fast filtering, selection logic, and buyer API calls. #### Platform Pick 1: Win Stakeholder Support Introduction Feeling like your affiliate marketing channel needs a boost, or you don’t have one yet? You’re on the right track! The first step is getting stakeholder buy-in. In this article, we’ll help you assess your current setup (or start from scratch), identify pain points like messy tracking, high costs, or missing features, and build a strong case for upgrading to a new platform. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Take a Look at Your Current Affiliate Setup First thing you need to do is take a long, hard look at your current affiliate program (if you have one). What’s working? What’s not? Maybe you’re not even using affiliate marketing yet, and that’s okay! If you are, though, what’s giving you headaches? Is it messy tracking that’s making your affiliate program and commissions look uncompetitive? You could be paying the same commissions as competitors but only tracking a fraction of the traffic (thanks, cookies). Or maybe your current solution is way too pricey, especially if you’re dealing with big volumes (hello, affiliate networks taking a 25% cut just for sending one email to affiliates per month). And let’s not forget about missing features – like, does your current setup support lead generation or other things that could help you grow? Or is your IT team buried in work? Whatever the problem is, it’s a good idea to write it down first. Understanding these pain points is the key to making the case for upgrading your affiliate platform. Build Your Case for the Platform You’ve got to show to your stakeholders why it’s necessary to start or upgrade to a new platform. Start by highlighting the benefits. If tracking is a mess, explain how the new platform will make tracking simple and accurate, so you can pay affiliates fairly and keep them delivering results. If payments are a headache, a better platform can automate the process, reduce mistakes, and save you loads of time. Is your current solution burning a hole in your budget? A new platform could give you more value for the price. It might be cheaper (your finance team will love it) or offer better features that help you make more money. If your affiliates are not interested in what you’re offering now, a new platform with advanced features might get them excited. New features and improved flexibility could be exactly what you need to win them over and supercharge their performance. If your IT team is overloaded and the current platform is taking up all their time with technical problems, a new one could take care of that, letting them focus on more important things. But, most importantly, frame it in a way that resonates with the people you’re pitching to. Show how this change will solve their problems, make things more efficient, and ultimately support the company’s goals. Get everyone on board by showing them that investing in a new platform is a win-win! Important Details to Cover Affiliate marketing is growing globally by 10% year over year. It accounts for 16% of total revenue worldwide, and for some businesses (especially service providers), it can be as high as 50%. How much of your revenue comes from affiliate marketing? If it’s less than that, something’s wrong. Take a look at your competitors – are they using affiliate marketing? How big is it for them? Don’t forget to check in with your affiliates too. Ask them what they wish you were offering. It’s not always just about higher commissions (though that can be a result of bad conversion tracking and paying just for the traffic since you don’t track the other part). Often, affiliates are missing key features or other benefits. And here’s the most important part – don’t just react to what your competitors are doing. Think bigger. How can you dominate your market with affiliate marketing? Think about how it can truly help you stand out. Get Everyone Onboard When presenting to stakeholders, keep it short, simple, and to the core of things. Remember, they’re not affiliate marketing experts and may not even know that something like that exists. So, start slow. Focus on Each Department’s Needs Keep it focused on what matters most to each department: For IT, it means less technical work and fewer headaches. For Finance, it’s more cost-effective solutions and better ROI. For Marketing, it provides a new traffic source of customers. Show them how investing in the platform aligns with their goals and supports the business as a whole. Include Affiliate Insights To strengthen your case, gather insights from current or potential affiliates. If you already have affiliates, ask them: “What’s working for you, and what could be better?” or “What features do you wish we had to make your job easier?” If you don’t yet have an affiliate program, reach out to larger affiliates you’d like to attract. Ask questions like: “What would convince you to join our affiliate program?” or “What tools and features do you need to maximize your performance with us?” Their responses will provide valuable insights into what your affiliate program needs to succeed. Emphasize Long-Term Investment Finally, emphasize that this is an investment in the future – long-term growth and scalability. Reassure them that while the start or switch to a new platform may seem complex, the benefits will outweigh the challenges in the long run. Keep the conversation grounded in practical terms and avoid technical jargon to make sure everyone is on the same page. The Sooner You Start, The Sooner Your Affiliate Channel Grows Don’t wait for the perfect moment to pitch the idea. The sooner you present the benefits of a new platform to your stakeholders, the sooner you can start seeing those long-term results. Now is the time to act – start laying the groundwork for a new affiliate platform and get everyone onboard. With the right platform, you can increase your affiliate revenue, make your program more competitive, and set yourself up for growth. Don’t just follow your competitors, lead the way. The future of affiliate marketing is in your hands! Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 10: Business, Legal, and IT Prep Introduction Now that you’ve narrowed down your platform choice, it’s time to make sure everything checks out from a business, legal, and technical perspective. This step involves bringing your top pick to your specialists—compliance, legal, finance, IT, and product teams—so they can confirm that it aligns with your goals and requirements. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Assess Business and Technical Needs Take your top platform pick to your compliance, legal, and IT teams for a quick review. You’ve chosen your winner based on the vendor’s provided information. Now your specialists can take a closer look and confirm that everything checks out before moving forward. Plus, it gives them a heads-up to start preparing for any work related to integrating the new platform. Occasionally, a blocker may arise – like a compliance issue where the vendor claims GDPR compliance but stores data outside the EU – potentially disqualifying the winner. This is perfectly normal. It’s better to catch these issues now rather than waste time with multiple reviews earlier in the process. By focusing on your top pick first, you save your team from reviewing all the top 3 or 5 contenders unnecessarily. If a blocker does appear, you can quickly shift to your second-choice platform with minimal delay. Product: Review which products you’ll promote, decide the promotion method, and determine the compensation model. IT: Check the integration from a technical perspective by mapping out all the requirements and features you need. Compliance: Confirm processes for adhering to regulations like GDPR or local advertising laws. Legal: Draft both General Terms and Conditions for your affiliate program and any other Specific Legal Contract. Finance Team: Validate commission structures and ensure the proposed payouts align with budget expectations and profitability goals. Define What You Want to Promote You need a clear idea of what you’ll promote through affiliates. You may have multiple products, each with unique requirements and business models, that need to be carefully considered and factored into your analysis. Identify Products or Services Start by listing the products, services, or offerings you want affiliates to promote. Think about: What products or services do you offer, and are you planning to promote all of them through your affiliate program, or just a select few? Which products drive the most revenue or have the highest potential? Are there any new services you’re looking to grow through affiliate channels? If you offer multiple products, you might consider integrating them into your new affiliate platform gradually, starting with the most promising ones. Pro Tip: Even if you choose to integrate products one by one, conduct the business analysis for all of them beforehand. This ensures the platform can support the unique requirements of every product from the start and you won’t be surprised later. Match Offerings to Affiliate Types Think about how your affiliates will interact with these products: Are you promoting clicks, leads completed sales or any other type of conversion? Will affiliates drive traffic to your website, use API integrations, or embed forms? Choose the payout model that best fits your strategy and decide if you’ll offer different commissions for specific products or actions. Pro Tip: If your business provides services but doesn’t currently use Lead generation or API integrations, be extra selective when choosing your affiliate platform. Chances are, you’ll need these features in the future – whether it’s a strategic decision or a necessity to accommodate a major affiliate bringing in traffic. Develop or refine your go-to-market strategy and carefully review the payout structure for each product to ensure it aligns with your affiliate goals and market dynamics. Analyze every conversion goal in the customer journey, calculate the average commission for each goal, and decide which model works best for your go-to-market approach. [table id=6 /] Outline How You Want to Promote It Plan Technical Integration. Will affiliates use: Links: Traditional and easy to set up. APIs: For seamless lead sharing or advanced functionality. Embedded Forms: To collect leads directly on affiliate websites. Dive into the technical aspects of how the program will function: Integrations: List the systems that need to connect with your platform (e.g., CRM, payment gateways, lead management tools). Tracking Methods: Decide whether to use cookies, S2S tracking or a mix. Data Security: Ensure the platform meets security standards for handling customer and affiliate data. Scalability: Plan for growth—ensure the system can handle increased traffic, leads, and affiliate activity. Determine how traffic and conversions will be tracked (e.g., cookies, S2S tracking or combination). Consider how this setup will grow with your business. Think about flexibility for adding new affiliates, products, or commission structures in the future. All of this will require some input from your IT team, so make sure to go over everything with them to ensure it all works smoothly. Pro TIP: Document Everything. Organize these requirements into a clear document. This will serve as a guide for internal teams and help you confirm alignment with your business goals. Present Your Plan Clearly Share your business analysis document with these teams, including: What you plan to promote. How you plan to promote it. The business and technical requirements you’ve outlined. Any specific concerns or questions for each team to address. Be Open to Adjustments Expect feedback and be prepared to revise your plan. This step is as much about refining your strategy as it is about validation. Teams may identify gaps, risks, or opportunities you hadn’t considered. Align on a Final Plan Once feedback is incorporated, ensure all teams are aligned on the updated strategy. This collective agreement will make the integration of a platform more streamlined and efficient. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. Resources [1] Wikipedia. Article Name. In: Wikipedia.cz [online]. Available on: https://cs.wikipedia.org #### Platform Pick 11: Integrate and Test it Introduction When it comes to affiliate marketing, tracking clicks and leads is key to making sure you’re paying affiliates correctly and measuring success. But it’s not just about the clicks – it’s about having a solid setup that tracks traffic, captures conversions, and reports everything back to the affiliate platform. In this article, we’ll walk you through how to structure your affiliate links, track traffic using pixels, and handle leads, whether they’re generated on your site or through APIs. We’ll also cover how to deal with cookie consent and what to do when pixel tracking isn’t enough. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Getting Clicks and Leads Clicks Before you start accepting clicks, you need to figure out how the affiliate link will be structured, making sure it’s both easy to use and accurate for tracking. Typically, the affiliate link won’t directly include the affiliate ID in the URL, as this is usually handled within the affiliate platform itself. The link should serve as a single entry point for all affiliate traffic, keeping things consistent for attribution across other marketing channels. Here are two options you can use to structure the link: UTM Parameters: Using UTM parameters is a common way to track traffic sources in tools like Google Analytics. Adding these parameters to your affiliate links lets you track where the traffic is coming from (like the affiliate partner, campaign, or medium). Here’s an example: https://example.com/?utm_source=affiliate&utm_medium=link&utm_campaign=campaign_name Custom Parameters: If you want more specific tracking, you can use custom parameters, like unique tracking IDs or lead information. This is helpful if you want to keep the affiliate parameters hidden and make them less obvious to your users. For example: https://example.com/?aid=12345 Leads For accepting leads, you’ll need to define the API methods and fields required for each product to send leads to your CRM. This ensures the data is consistent across all platforms, and the affiliate’s contribution is tracked accurately. Pro Tip: To avoid paying for the same lead twice, track affiliate data at the lead level as well. This helps prevent duplicate payments and ensures accurate tracking. Tracking When a customer clicks on an affiliate link, they’ll land on your website. To track this visit, you’ll implement a tracking pixel from the platform, which fires on every page. This pixel stores the affiliate’s tracking data in a cookie. If the customer converts (like making a purchase or submitting a lead) within the tracking period (usually 30 days), the pixel will send a conversion event to the affiliate platform. Cookie Consent Considerations If you’re in a jurisdiction that limits cookie usage (like GDPR), you’ll need to confirm whether it’s okay to classify this pixel as technically required for the website to function, meaning it can fire without explicit consent. If it’s not allowed, the pixel will only be used once the customer gives consent, which will limit how much traffic you can track. Pro Tip: Studies show that cookie consent rates range from 72.5% to 82%, meaning that while affiliates will send you 100% of the traffic, you’ll only be able to track around 77% of it using cookie tracking. To compensate for this, either increase commissions to account for the lower consent rates or combine cookie tracking with postback tracking to get closer to full attribution. When Pixel Tracking Falls Short – Postback Integration If the conversion happens outside your website (like via API-based lead generation or post-purchase conversions), pixel tracking won’t work. In this case, you’ll use Postback (Server-to-Server or S2S request) to track conversions. For example, when a visitor lands on your site via an affiliate link, you’ll store the affiliate tracking info (like affiliate ID and campaign data) in a table. If the visitor converts during the same session, you won’t need cookies or consent because the affiliate parameters are already stored with the lead or purchase data. Lead Generation via API – Simplified Tracking For lead generation, where the conversion happens outside your site (like through an API submission), tracking is straightforward. The lead goes directly to your CRM with the affiliate parameters, and no cookies are involved. This ensures the affiliate’s referral is tracked without needing cookie consent. Combining Pixel and Postback Tracking The best solution combines cookie tracking for visitors who consent to cookies (about 77% of users) and postback tracking for those who don’t consent but convert during the same session (roughly 15%). However, there will always be some untracked traffic when cookie consent is required, especially if the user declines cookies. Attribution Attribution should be based on the lead or purchase event to properly credit the conversion from affiliate links, API calls, or embedded forms. It’s important to avoid overlap between marketing channels so that affiliate traffic gets the right attribution without being overwritten by organic or non-paid channels. Pro Tip: Set your attribution to give credit to the last paid traffic source. Exclude organic channels from attribution so they don’t override the affiliate’s contribution if the customer returns later to complete a purchase. This ensures fair compensation for your affiliates and accurate reporting. Don’t forget to document the attribution flow and what overwrites what, so everyone (including affiliates) knows how it works. Everyone tends to forget about it once it’s setup. Testing Testing is key to making sure everything runs smoothly. Set up a test affiliate account and generate an affiliate link. Click it, complete the tracked action (like a purchase or lead), and ensure the conversion info is sent to the tracking platform. If the conversion requires approval, make sure that it gets done and is tracked too. For leads, fill out the embedded form or send a test lead via API and check if it’s properly tracked. Make testing a regular habit. Ideally every quarter to catch any hidden issues and keep everything running smoothly. Pro Tip: Test attribution and cookie tracking by leaving the site and coming back through a different channel, like organic search. This helps ensure the right source gets credited. Don’t Be Afraid to Reevaluate Your Choice Let’s be real – salespeople can sometimes stretch the truth, and misunderstandings happen. Even after doing your research and checking all the boxes, you might find during integration, testing, or even after launching that the platform you chose isn’t working as expected. Some features you thought were included might be missing, or certain functions might be so poorly designed that they require workarounds or are not usable at all. Don’t hesitate to rethink your decision. If the platform isn’t supporting your needs now, it’s unlikely to do so in the future. The longer you stick with a poor solution, the more painful and costly the transition will be later on. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 12: Rollout Introduction As you approach the official rollout of your affiliate platform, it’s time to take a step back and make sure everything is in place. A smooth launch doesn’t happen by accident—it requires a thorough review of all tasks, checks, and preparations. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Review Your Checklist Now that you’re getting closer to the official rollout, it’s time to take a step back and double-check everything. Before you launch, ensure that all your integration tasks have been completed and that your platform is ready to go. We created the checklist in Platform Pick 2: Create a Checklist, which covers all the essential aspects of: Business and Technical Requirements Legal Compliance and Documentation Platform Testing and Integration Internal and Partner Communication (in progress) Marketing and Website Updates (in progress) Post-Launch Monitoring Internal Communication Make sure all departments (IT, marketing, legal, finance, support) understand the launch plan, including timelines and roles. Send out a summary or hold a quick meeting to get everyone aligned.Ensure every team knows how to use the platform and what their responsibilities are. Clearly outline responsibilities for each team: Support: Address affiliate inquiries. IT: System checks and integration. Marketing: Affiliate promotion and materials. Legal: Compliance and contracts. Finance: Set up payouts. Set Up Communication Channels Use tools like Slack or project management software to create dedicated channels for updates and quick issue resolution. Keep the lines open for any last-minute questions. Partner Communication It’s time to communicate with your partners to ensure a smooth launch. Here’s how to do it effectively. Inform Partners Early and Highlight Key Features Give your affiliates a heads-up about the new platform, explaining its benefits and any changes they should expect. Share the new platform’s key features that will benefit your partners, like improved tracking, reporting, or payout flexibility. Provide Training and Resources and Make Onboarding Easy Offer clear training materials (guides, FAQs, webinars) to help your partners get comfortable with the platform. Ensure the onboarding process is simple and provides step-by-step instructions for setting up accounts and understanding the system. Communication Plan Set up a communication plan to keep partners updated on progress, issues, and platform enhancements. Be available for extra support during the transition, answering questions or helping with setup. Gather Feedback After launch, collect feedback from partners to identify any issues or areas for improvement. Marketing and Website Updates Make sure your website reflects the new platform. Add information about its features, benefits, and how affiliates can sign up. This is the first place your affiliates and potential partners will check, so keep it clear and informative. Direct new affiliates to the sign-up page, but make sure there’s also a login button for those who are or will be already Social Media and Email Campaigns Promote the new platform via social media and email campaigns. Let affiliates and partners know that the platform is live and encourage them to check it out. Keep the messaging simple and focused on the benefits. Post-Launch Monitoring Keep an eye on the platform’s overall performance. Monitor site speed, uptime, and the functionality of key features. Use analytics to identify any issues early, like errors in conversion tracking. Affiliate Activity and Feedback Check how your affiliates are using the platform. Are they signing in, promoting, and generating sales as expected? Collect feedback from them to see if there are any usability issues or feature requests. Address Issues Quickly If any problems arise, address them fast. Whether it’s a bug, a technical issue, or a process misunderstanding, quick resolutions will keep your affiliates happy and the platform running smoothly. Track Conversion Data and Payouts Keep a close eye on conversion tracking and payout calculations. Ensure everything is being tracked accurately and that commissions are being paid out correctly. Any discrepancies should be addressed immediately to avoid confusion or disputes. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 2: Create a Checklist Introduction Integrating a new affiliate marketing platform can seem like a lot of work, but don’t worry – we’ve got your back! By breaking the process into clear, manageable steps, you’ll be able to stay on track and get things done without the headache. In this article, we’ll show you how to define the scope of the integration, create a checklist, and set up a system to track your progress. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Define the Scope of the Integration Start by listing the key components that need to be integrated into your affiliate platform. These could include: Tracking: How will clicks, leads, and sales be tracked, attributed and reported? CRM: What integrations are needed to sync affiliate data with your CRM system? Marketing tools: How will marketing materials and reports be managed through the platform? Payments: What’s your plan for paying affiliates? Define the Team Involvement List out which departments will play a role in the integration: IT Team: Responsible for the technical integration, ensuring everything is compatible. Marketing Team: Will help set up banners, emails, and other affiliate marketing materials. Legal Team: Responsible for drafting contracts, terms of service, and ensuring GDPR compliance. Finance Team: Will help out with payment models, commission structures, and handle affiliate payouts. Realistic Expectations Be clear about the timeline and the resources needed. Are you aiming for a full platform rollout, or will it be a phased approach where you start with one product or segment and add others later? Create a Checklist Start by identifying the core tasks that need to be completed for the integration. This will include the platform selection, tracking strategy, technical setup, legal work, and more. Some key tasks might include: Define Your Needs & Win Stakeholder Support: Secure buy-in from key decision-makers and outline clear goals and requirements for the affiliate platform. Evaluate Platforms & Choose Your Top Picks: Research potential platforms, send out RFPs, conduct demos, compare pricing, and select the best platform based on features and value. Prepare Teams for Integration: Coordinate with internal teams (business, legal, IT) for compliance, technical requirements, and integration planning. Platform Setup & Data Migration: Configure the platform, integrate with CRM and payment systems, and migrate necessary data from the old system. Testing & Onboarding: Conduct internal and external testing to ensure everything works as expected, then prepare onboarding materials for affiliates. Launch & Rollout: Officially launch the platform, ensure all teams and affiliates are aligned, and ensure the integration is running smoothly. Break Tasks into Smaller Actions Each task in the checklist should be broken down into smaller, manageable actions. For example, under the Evaluate Platforms & Choose Your Top Picks task, smaller actions might include: Schedule demo calls with each vendor to see the platform in action and take notes Review the pricing models and compare them to the features offered. Score each platform based on the demo, pricing, features, and overall fit. Narrow down the list to 2-3 platforms that best meet your needs. and others By breaking down tasks, you ensure nothing gets overlooked and each step can be tracked. Assign Tasks to the Right Teams Next, assign each task to the responsible team. Be sure that everyone knows what they need to do and when it needs to be done. For example: IT Team: Platform configuration, data migration, testing integrations. Marketing Team: Prepare banners, ads, and affiliate onboarding materials. Legal Team: Review and finalize contracts, GDPR compliance. Finance Team: Set up payment structures, commission tracking. Set Deadlines and Prioritize Assign realistic deadlines for each task, keeping in mind that some tasks are dependent on others. Make sure to prioritize the most critical actions (like legal compliance) so they are completed first. Use your project management tools (Trello, Asana, etc.) to keep track. Create a Status Column In your checklist, include a status column to track the progress of each task. This could include statuses like: Not Started In Progress Completed Blocked Set Up a Status Document for Progress Tracking This document will help you keep track of progress and ensure everything stays on schedule. It’s also an important tool for reporting to stakeholders so they can stay informed. Keep the status document simple but detailed enough to track key aspects of the integration. Include Date in the Title and Name of the File Start by adding the date to the title of your status document so it’s easy to see and track progress over time. This ensures that anyone reviewing the document can quickly identify which week is covered. Create Timeline Build a timeline (harmonogram) in a table format divided by weeks. This will give you a clear overview of what needs to be done during each week. Some tasks may span multiple weeks, so make sure to overlap activities as needed. This section will help everyone see the bigger picture and ensure you stay on track. Example of a timeline: [table id=5 /] Status for Each Department Include a status section for each department involved in the integration. For example, list the IT team, marketing, legal, finance, etc., with a brief summary of their progress and the main person responsible for each task. Example: IT Team – John Doe – Integration setup is 75% complete, working on final testing. Marketing – Jane Smith – Affiliate materials are in progress, expect completion next week. Details for Completed Tasks Write down the details of completed tasks if needed. This can serve as a notebook for tracking all the more complex details and meetings, helping you keep track of both inputs and outputs. Next Steps In this section, outline the next steps for the upcoming week. This section can break down the timeline further, outlining specific steps that will be taken. Things to Solve List any challenges or roadblocks that need to be addressed now or later so nothing is left out. For example: “Compliance check pending” “Integration issue with payment gateway.” Link or Embedded Checklist Finally, embed or link to the detailed checklist in your status document. This will give everyone easy access to the full list of tasks that need to be done and ensure alignment between your weekly updates and the larger project goals. Prefilled Example Good news – we’ve already done the heavy lifting for you! Thanks to our experience as affiliate consultants, we’ve created the checklist based on our expertise. We’ve helped businesses with this dozens of times, so you can learn from our know-how and get started quickly. Available here How to Use It Open the Example Table: Click here to access the prefilled Google Sheet. Make a copy so you can edit and adapt it to your needs. Review the Structure: Familiarize yourself with the categories and scoring system. Customize: Replace the example inputs with your own and adjust as necessary. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 3: Create a Feature Comparison Table Introduction You’re here because you want the best tool for your needs, right? Not just something that “kind of works” but a platform that actually ticks all the boxes – without nasty surprises later. Here’s the thing: software providers love to claim they do it all. “Oh, yeah, we’ve got that feature!” they’ll say. But when it’s time to actually use the tool, suddenly that feature doesn’t work how you expected. That’s where your trusty feature table comes in. It’s not just a fancy spreadsheet – it’s your BS detector and decision-making buddy. In this article, we’ll walk through how to set up a table that makes demo calls a breeze. You’ll assign priorities, flag deal-breakers and have a clear plan to get real answers from vendors. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready to get organized? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Creating the Feature Comparison Table Let’s get down to business – building your feature comparison table. This is the backbone of your decision-making process, so it’s worth putting in the effort now to save headaches later. Think of it as your personal cheat sheet for cutting through the noise and figuring out which platform is actually worth your time. Step 1: List the Features That Matter Start by listing all the features you need. Focus on what’s essential for your business today and, even more importantly, what could be crucial in the future. Why? Because the wrong tool could limit or even block your growth within a year. Imagine landing a promising affiliate who requests a feature your platform doesn’t support – suddenly, that missing functionality becomes a roadblock. Make sure to capture everything – from must-haves to nice-to-haves – so your tool can grow with you, not hold you back. Pro TIP: break down complex features into smaller, distinct parts so you can compare them easily. For instance, if you need to handle both bonuses and penalties, don’t group them together under “commission adjustment.” Some platforms might only support one of those, and you don’t want to miss that detail. Step 2: Assign Priorities Here’s the trick to making this table work: assign a priority level to each feature. Use a scale, like 1 to 3, where: 3 = Essential (you can’t live without it). 2 = Important (you really want it but could work around it). 1 = Nice-to-have (would be cool, but not a dealbreaker). Why make the highest number the highest priority? Simple – because you’ll be calculating each platform’s total score, and the higher the score, the better the match. It’s a straightforward way to identify the strongest contenders. If there’s a feature that’s absolutely critical – like Lead Generation for the lending industry – boost its points even more. Platforms without it shouldn’t be crowding the top of your list. By prioritizing this way, you ensure only the best-fit options make it to your final selection. Pro TIP: Keep it realistic. If everything’s marked as essential, your table won’t help you narrow down options. Add KO Factors Here is where it gets interesting. KO factors are your dealbreakers – things that automatically eliminate a platform from the running. These could be things like non-compliance with GDPR or a lack of support for your region. Assign negative weights to these so they stand out. Step 3: Write Clear Descriptions for Each Feature Now it’s time to get specific. For every feature, write a short, clear description of what it is and what it should do. Keep it simple- just enough to explain it without overloading on details. This will come in handy later when you’re putting together the request-for-quote document. Think of it as laying the groundwork for smooth communication with vendors. Step 4: Set Up the Table Pop all this into a spreadsheet. Create columns for the feature name, priority, and the platforms you’re considering. Leave the platform columns blank for now – you’ll fill them in during your demo calls. Your table might look something like this: Step 5: Be Ready to Adjust Remember, this table is a living document. As you learn more during your demo calls, you might discover new features to add or adjust priorities. That’s totally fine – it’s all part of the process. By the end of this step, you’ll have a clear, organized way to evaluate platforms. And trust me, this table will save you from a lot of “we thought they could do that” regrets later on. Next up? How to use it during demo calls. Prefilled Example We’ve done the heavy lifting for you! Using our in-depth research across dozens of tools on the market and over 30 features, we’ve prefilled a feature comparison table to give you a head start. This isn’t just a random list – we’ve carefully analyzed all platforms on the market and included the features that matter most. Available here. This example showcases how to organize your features, assign priorities, and use weights effectively to evaluate platforms. It’s a great reference to guide your own table setup and customization. How to Use It Open the Example Table: Click here to access the prefilled Google Sheet. Make a copy so you can edit and adapt it to your needs. Review the Structure: Familiarize yourself with the categories and scoring system. Customize: Replace the example features with your own and adjust weights as necessary. Populating the Table You’ve got the table set up – now it’s time to put it to work. This tool is your secret weapon for cutting through the noise and finding the right affiliate platform. Customize it, fill it with real data, and let it guide your decision. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 4: Defining Your Needs Clearly Introduction Let’s face it – nobody knows your business better than you do. But here’s the catch: the person giving you a demo probably doesn’t. They’re not living in your world. They’re likely running through a pre-made script, hitting the same talking points they’ve shared a dozen times before. That’s why this step is so important. You need to spell out exactly what you do, what you need, and what’s non-negotiable – like you’re explaining it to a total newbie. Why? Because if they don’t get your business, they can’t show you how their platform fits. And if they can’t show you that, you’ll end up wasting time on irrelevant features and sales fluff. In this article, we’ll walk through how to draft a no-nonsense document that lays it all out: who you are, what you’re looking for, and why it matters. This isn’t just for them – it’ll also help you get crystal clear on your priorities. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Defining Your Business This section is where you introduce your business in simple, clear terms. Remember, the goal is to ensure that even someone unfamiliar with your industry can understand what you do and what you need. Who We Are Start with a brief overview of your company and its role in the market. Focus on your core mission and the value you bring to your customers. For example: “We are Company.com, a leading [your product] platform in [your countries]. Our mission is to [your goal] by [how you achieve it].” What We Do Explain your business model in a straightforward way, emphasizing how you operate and generate value. This includes the services you provide and your relationship with affiliates and advertisers. For example: “Our platform helps customers [what you do] by [how you do it]. We partner with businesses to [your collaboration goal] and ensure [desired outcome]. Leads are managed through [your processes] and delivered to partners via [your technology or system].” Key Goals Highlight the business goals you aim to achieve with the affiliate platform, ensuring the vendors understand your priorities. For example:“Our primary objective is to [your main goal], focusing on [specific focus area]. We aim to [secondary goal] while ensuring [flexibility/adaptability for specific needs].” Stating Your Needs Here’s where you get crystal clear about what you’re looking for in an affiliate platform. Think of it as your wishlist – but practical. The goal is to outline your needs so that even someone new to your industry can understand what you expect. Pro tip: Write it as if you’re explaining it to someone completely unfamiliar with your business. The simpler, the better. Remember, many demo presenters will review briefly the document before the call – if it’s too complicated, you’ll waste time clarifying instead of getting answers. Expected Volumes Here’s where you set expectations for the vendors. Be transparent about your growth plans, so they know what they’re dealing with. This isn’t just about what you’re doing now—it’s about where you’re headed. A good platform needs to handle not just today’s traffic but tomorrow’s growth, too. Current Volumes Start with where you are right now. Be honest – it’s fine if your volumes aren’t huge yet. Projected Volumes Now for the exciting part: where you want to be. Give vendors a realistic but ambitious forecast for 1, 2, or 3 years in the future. Having these traffic milestones ready is crucial because public pricing often states something like ‘for every additional 1,000 transactions, clicks, or whatnot above the package limit, you pay X USD extra.’ Knowing your expected volumes ensures you get accurate pricing tailored to your needs. Prefilled Example To make things easier, we’ve prepared an example Google Document template that outlines how to structure your business overview, requirements, and expected volumes. This template ensures clarity and helps vendors understand your needs right away. Available here. Pro TIP: If you’ve done a good job filling out the Feature Comparison Table, you can simply copy and paste the features. Sharing the Document Once you’ve crafted your business description and detailed your requirements, it’s time to share the document with vendors. This step ensures they fully understand your needs before any demo calls, saving time and avoiding confusion. Here’s how to do it right: Step 1: Create a Google Document Why Google Docs? It’s easy to share, accessible to everyone, and allows for real-time updates (on your end). Plus, you can control access. How to Set It Up: Write your document in simple, clear language. Include all the key sections: Business Overview, Requirements, Expected Volumes, and any additional notes. Use headings and bullet points for clarity. Step 2: Set Permissions Share the document as “View Only” to prevent edits or comments by vendors. If additional stakeholders (e.g., internal team members) need to provide input, share a separate editable version with them beforehand. Step 3: Include a Link in Your Email When you send your request for a demo or proposal, include the link to your Google Document. Here’s an example: “Attached is a detailed overview of our business, requirements, and expected volumes. Please review it prior to the demo to ensure a productive discussion.” Here’s an example template to get you started: Google Doc Example. Step 4: Use It During the Demo Use the document as your guide to ask questions and verify claims. Encourage the vendor to reference the document during their demo. This helps keep the focus on how their platform meets your specific needs. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 5: Hunt for the Right Platform Introduction You’ve nailed down your needs and built your Feature Comparison Sheet – now it’s time to hunt for the right platform. This step is all about exploring your options and building a solid longlist of tools worth a closer look. In this article, we’ll show you how to find platforms that match your must-haves, narrow down your choices, and get organized for the next steps. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Gather Potential Platforms It’s time to start your search. The goal here is to cast a wide net and identify platforms that could potentially meet your needs. Don’t worry about narrowing things down yet – that comes later. For now, focus on gathering as many viable options as possible. Here’s how: AI AI can make your platform search much faster – if you know how to ask. Since you already have your brief from the “Defining Your Needs Clearly” section and your Feature Comparison Table, paste them both into the chat and ask: “Based on this brief and feature table, suggest affiliate or leadgen platforms that match these requirements.” Then, ask AI to expand the list: “Now give me at least 20 possible tools – not just the biggest or most popular ones.” AI tools often default to listing only a few of the most well-known platforms, which may not actually fit your needs. By pushing it to provide more options, you’ll uncover smaller, specialized tools that could align much better with your business.You can also ask AI to summarize user feedback from review sites. Search Engines Start with the obvious: Google. Use specific keywords based on your must-have features from your Feature Table. For example: Affiliate marketing SaaS with API Affiliate platform for lead generation Lead Generation Platform Review Sites Platforms like G2, Capterra, and TrustRadius are good for finding affiliate platforms. These sites offer: Lists of tools with feature comparisons. Real user reviews to help you understand strengths and weaknesses. Insights into pricing and usability. Industry Communities Tap into your network or explore online communities: LinkedIn groups focused on affiliate marketing or SaaS tools. Reddit threads or forums where professionals discuss tools they’ve used. Industry-specific Slack groups or meetups. Pro TIP: Ask your Affiliates what platform they like. Competitor Research Check what platforms your competitors are using. Often, you’ll find this information in case studies, testimonials, or public success stories. If they’re using a tool successfully, it might be worth exploring for your business. Case Studies Search for case studies or whitepapers from platforms that detail how businesses like yours have benefited. This can provide insights into their strengths and alignment with your needs. Cross-Check with Your Feature Table Now that you’ve gathered a list of potential platforms, it’s time to put your Feature Comparison Table to work. This step is all about filtering through your options and identifying which platforms align best with your needs. You don’t know everything about these platforms yet, and most of their features might not even be listed on their websites. But some preliminary research can help you avoid entering demo calls with a blank table. Here’s how to do it: Match Features Against Your Table Take each platform from your longlist and compare its features to the ones in your Feature Comparison Table. Focus on must-have features and KO factors. If a platform lacks something critical, consider removing it from the list. Look for platforms that go above and beyond by offering standout features that could benefit your business. Make a note for the upcoming demo call. Add Notes for Each Platform For every platform that aligns with your table, write down why it made the cut: Does it have a key feature others don’t? Is it particularly strong in areas that matter most to you? If a platform is missing some features but still looks promising, mark it for follow-up during demos. Don’t Overthink It This is still the early stage, so don’t worry about ranking platforms or making final decisions yet. The goal here is to trim your list to platforms that genuinely seem viable. Don’t worry if you’re not precise yet or can’t find all the information on their website. Create your Longlist Now that you’ve cross-checked your options with the Feature Comparison Table, it’s time to create a clear and organized longlist. This step lays the foundation for deeper evaluations and vendor discussions. Finalize Your Longlist Narrow down your list to around 10 platforms that align with your key requirements. Focus on tools that meet most of your must-have features and avoid any KO factors. Don’t worry if some platforms aren’t perfect—if they show potential, keep them on the list for further evaluation. Organize Your Findings Use the Table comparing the features you created earlier as a foundation to track and manage your selected platforms. Simply edit it to include information about the platforms you’ve shortlisted. Add or adjust the following columns to make it more useful: Platform Name: The name of the tool. Key Features: The standout features or reasons why it made your list. Initial Impressions: Brief notes on what caught your attention, such as positive reviews or specific strengths. Links: Direct links to the platform’s website, relevant reviews, or case studies for easy reference. Prepare for the Next Step Your spreadsheet will also serve as a tool to track findings during demo calls, helping you compare platforms side by side. Use this longlist as your guide when reaching out to vendors and scheduling demos. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 6: Send Out Requests for Proposals Introduction It’s time to reach out to the vendors and see what they bring to the table. This is where the magic starts (well, kind of). The email you send is more than just a message – it sets the tone for your interaction with each vendor. It should clearly communicate to the demo presenter that you have specific needs and expect the conversation to focus on addressing them. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Craft Your Outreach Email With your RFP document ready and vendors chosen, the next step is to reach out to them with a clear and professional email. This email sets the tone for your communication and ensures vendors understand the expectations. Keep It Short and Focused Your email should be concise while providing all the necessary details. Here’s what to include: A brief introduction about your company. A reason why you’re reaching out to this specific vendor. The attached RFP document and a request to review it before the demo. Deadlines for submitting their proposal or any key dates. An offer to answer questions or provide clarifications. Example Email Template Subject: Request for Proposal – [Your Company Name] Hi [Vendor Name],We’re [Your Company], and we’re currently exploring platforms to [your goal, e.g., streamline affiliate marketing operations]. Based on your platform’s features and expertise, we believe you might be a great fit for our needs.Attached is a detailed overview of our business, requirements, and expected volumes. Please review it prior to the demo to ensure a productive discussion.We’d appreciate it if you could submit your proposal by [deadline]. If you have any questions or need further details, feel free to reach out- we’re happy to assist.Looking forward to hearing from you.Best regards,[Your Name] Send the RFPs Now that your email is ready, it’s time to send out your Requests for Proposals. While many platforms provide online forms for inquiries or demo requests, this can sometimes be tedious. A faster and more efficient approach is to collect email addresses from each platform and send one email with all vendors in blind copy (BCC). Why Use BCC? Saves Time: Instead of filling out multiple online forms, you can send a single email to all vendors. Professional Privacy: Using BCC ensures vendors don’t see each other’s contact information, maintaining confidentiality. Collect Email Addresses Visit the contact or demo request pages on each platform’s website. Look for dedicated sales or support emails (e.g., sales@platform.com). If emails aren’t listed, use the platform’s contact form to request the appropriate email for RFP submissions. Send the Email Track Vendor Responses Use your Feature Sheet to track and organize Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 7: Demos with Vendors Introduction Demos are your chance to see if the platform is the real deal or just good marketing. A little prep goes a long way in making sure you’re in control and getting the answers you need. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Schedule Smart Demo calls require focus, and sitting through multiple in a row can cause fatigue, making it harder to stay sharp. To keep things manageable and productive, plan your schedule wisely. Don’t Overload Yourself Limit yourself to 2-3 demos per day to avoid fatigue and stay engaged. Spread the calls over a week or two, depending on how many vendors you’re evaluating. Leave time between demos to review notes, update your Feature Table, and prepare for the next session. Set Clear Expectations with Vendors Tell vendors upfront what you want to focus on during the demo. Example: “Please demonstrate [critical features] and show how your platform handles [specific scenarios].” Specify a time limit (e.g., 45 minutes to 1 hour) to keep the demo focused and efficient. Record the Demo Ask the presenter to record the session or record it yourself. Recordings are great for revisiting details later and sharing with your team. Confirm the Details Double-check the time zone, meeting platform (e.g., Zoom, Google Meet), and the call link ahead of time. Have the Feature Spreadsheet ready. Use It During the Demo Encourage the vendor to reference the document during their demo. This helps keep the focus on how their platform meets your specific needs. Use the document as your guide to ask questions and verify claims. Stay Sharp During the Demo The demo is your chance to dig into the details and see if the platform truly meets your needs. Here’s how to make the most of it: Be Firm, Not Passive Don’t just sit back and let the presenter run the show. Push for demonstrations of critical features and workflows. If they say, “Yes, we have that,” ask them to show it in action. Many platforms claim features they don’t fully support. Use Your Feature Table Actively fill in your Feature Table during the demo, noting: Whether features are present and how they work. Any gaps or issues you spot. Questions that still need answers. Make the goal clear: you want the table fully filled out by the end of the call. Focus on Functionality, Not Sales Talk Keep the conversation on how the platform handles your specific needs. Avoid getting distracted by features you don’t need or generic sales pitches. Discuss Pricing Briefly While the demo is about features, take a moment to confirm when they’ll send detailed pricing. Don’t let pricing dominate the call – save that for follow-ups if needed. Pro TIP: Ask About Demo Access. Ask if you can get temporary demo access to explore the platform yourself. They might say no (many vendors do), but it’s always worth asking. Review and Update Your Notes After the demo, go back to your Feature Table and fill in any missing details. Focus on how each feature works, not just whether it exists. Note any gaps or inconsistencies between the vendor’s claims and what was demonstrated during the call. Record Strengths and Weaknesses Create a “Pros and Cons” section for each platform. Highlight what impressed you and what seemed unclear or lacking. This summary will make it easier to compare platforms later. Note Questions for Follow-Up If certain features weren’t fully demonstrated or if specific details were unclear, make a list of follow-up questions. These can be addressed with the vendor in subsequent conversations. Evaluate Usability Think about how intuitive the platform felt during the demo. Consider whether it aligns with how your team operates or if it seemed overly complex or clunky. After all, it’s something you’ll be using. Pricing Decide whether the platform should move forward to the next stage of your evaluation process. If pricing wasn’t covered in detail, send a follow-up request to the vendor. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 8: Check Pricing and Value Introduction Pricing isn’t just about the numbers – it’s about understanding what you’re really paying for and whether the platform delivers enough value to justify the cost. Sure, you want something affordable, but cutting corners could mean missing out on critical features or scalability down the road. This step is all about gathering and organizing pricing information so you can see the full picture: what it costs today, what it might cost a year or two from now, and whether it aligns with the value it provides. This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Step 1: Gather Pricing Details Before making any decisions, you need a complete picture of the platform’s costs – not just for today, but for the future as well. Here’s how to ensure you get all the details: Ask for a Detailed Breakdown When reaching out to vendors, request a clear and thorough pricing breakdown. Make sure it includes: Base Costs: Subscription fees or license costs. Extra Charges: Additional fees for extra users, transactions, or advanced features. One-Time Fees: Setup fees, onboarding, or training costs. Scaling Costs: Costs associated with higher usage volumes (e.g., per 1,000 transactions or leads). Plan for the Future Pricing today is only part of the equation. Ask vendors for cost projections based on your expected growth: What would the cost look like at your current volumes? How would pricing change in 1 year, assuming growth in traffic or transactions? What would it cost in 2 years, if your business scales further? This ensures you’re not caught off guard by unexpected expenses as your business evolves. Organize Pricing Details Once you’ve gathered pricing information, it’s time to organize it in a way that’s easy to compare across platforms. The best way to do this? Use the Pricing sheet in your Features Table. Add Pricing to the Table The Pricing sheet is already set up to help you track costs alongside features. Here’s what to include for each platform: Base Costs: The starting price for using the platform. Extra Charges: Fees for additional users, transactions, or premium features. Scaling Costs: Costs projected for 1-2 years based on your expected growth. One-Time Fees: Any setup, onboarding, or training expenses. By filling in the Pricing sheet, you’ll keep all the essential information in one place, making it easier to evaluate both features and costs at the same time. Compare and Highlight Key Details Use the sheet to note any standout points, such as: Which platform offers the most competitive pricing at your current volumes. How costs scale over time and whether they align with your growth plans. Any unexpected or hidden fees that could impact the total cost. Evaluate Value for Money Once you’ve calculated the Total Cost of Ownership (TCO), it’s time to assess whether each platform offers value that matches its price tag. This step goes beyond costs – it’s about determining which platform gives you the best overall value. Match Pricing to Features Compare each platform’s pricing with its capabilities. Look for: Platforms that excel in must-have features while staying reasonably priced. Any features unique to a platform that justify a higher cost. Consider Scalability and Future Needs Evaluate how well each platform’s pricing aligns with your long-term growth. A tool that’s affordable now but skyrockets in cost as you scale may not be the right fit. On the flip side, a slightly more expensive platform that handles scaling smoothly could be a better investment. Assess Overall ROI Think about the return on investment each platform offers: Will it save time or reduce costs in other areas (e.g., automation, analytics)? Does it have features that could help you generate more revenue or attract affiliates? How does its usability and efficiency impact your operations? Expect Compromises Don’t expect to find the platform with the best features at the lowest price – it’s rare, if not impossible. Instead, focus on finding the best value for your money. Compromises may be necessary, so prioritize platforms that strike a good balance between features, scalability, and cost. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick 9: Choose Your Top Favorites Introduction You’ve done the legwork – built your Feature Table, evaluated demos, and gathered pricing. Now it’s time to tie everything together and start narrowing down your options. Think of this as the moment where logic meets intuition. How well do the platforms align with your needs? Did the demo presenters leave you with confidence or concern? And, most importantly, which platforms will support your business not just today, but as it grows? This is part of a series on how to pick the right platform for your needs. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Review Your Feature Table Now it’s time to put everything together – features, pricing, and your overall impressions – to start narrowing your options. Your Feature Table is your starting point, but it’s about more than just ticking boxes. Here’s how to approach it: Connect Features to Pricing Look at how well each platform’s features align with its pricing. Does the platform offer good value for the cost? Are you paying extra for features you don’t really need, or are must-haves missing despite a higher price tag? A platform with fewer features but great pricing might still beat one with all the bells and whistles that costs a fortune. Consider the People Behind the Platform Think about the experience you’ve had with the vendors. Did the demo presenters seem knowledgeable and genuinely interested in your needs? Were they responsive to questions and transparent about their limitations? A great platform can be overshadowed by poor support or communication, so factor in your gut feelings here. Evaluate How They Meet Must-Haves Revisit your list of must-have features and KO factors. How well does each platform meet your absolute requirements? Platforms that can’t deliver on these should be eliminated, no matter how great other aspects may seem. Factor in Scalability Consider how well each platform will handle your growth. A tool that works now but struggles as your volumes increase isn’t a long-term solution. Platforms that can scale smoothly, even if they cost a little more, should get extra points. Assign Scores and Identify Your Top Picks Give each platform a score based on how well it meets your must-haves, scalability, pricing, and overall experience. Use a simple scoring system – like a 1-10 scale – and include a notes column for any standout strengths or weaknesses. Identify the platforms with the highest scores as your top picks. Ideally, this will leave you with 2-3 contenders to move forward with. Identify Deal Breakers With your top picks emerging, it’s time to dig into what could disqualify a platform. This step is about spotting the red flags and making sure you’re not setting yourself up for surprises later. Check KO Factors Revisit your list of KO factors. These are the non-negotiables – if a platform doesn’t meet them, it’s out. No matter how great the pricing or features might seem, platforms that can’t deliver on your critical needs shouldn’t move forward. Look for Red Flags Evaluate your interactions and demo experiences for potential warning signs: Overpromising: Did the vendor claim to have everything you needed but couldn’t demonstrate it in the demo? Pricing Gaps: Were there hidden costs or vague pricing terms that could lead to surprises later? Poor Support: Did the vendor seem unresponsive, disorganized, or uninterested in understanding your needs? Choose the Winner Now it’s decision time. With your top contenders narrowed down, it’s time to weigh everything – features, pricing, scalability, and overall impressions – and make the final call. Here’s how to confidently choose the platform that’s right for you: Lay out your top picks and compare them across all critical categories: Features: Which platform meets your must-haves most comprehensively? Pricing: Which one offers the best value, factoring in current costs and scalability? Usability: Which platform feels more intuitive and aligned with your workflows? Choose the platform that ticks the most boxes and feels like the best fit for your business. Trust, but verify You’ve chosen your winner based on the vendor’s provided information. In the next article, we’ll dive into how your specialists can take a closer look and confirm that everything checks out before moving forward. Occasionally, a blocker may arise – like a compliance issue where the vendor claims GDPR compliance but stores data outside the EU – potentially disqualifying the winner. This is perfectly normal. It’s better to catch these issues now rather than waste time with multiple reviews earlier in the process. By focusing on your top pick first, you save your team from reviewing all the top 3 or 5 contenders unnecessarily. If a blocker does appear, you can quickly shift to your second-choice platform with minimal delay. Where to next Explore Our Guide to Choosing the Best Affiliate Platform Platform Pick: How to choose the right Affiliate Platform Real guidance from consultants who’ve helped dozens of companies choose the right affiliate platform. Platform Pick 1: Win Stakeholder Support Discover how to grow your affiliate program, drive better results, and get stakeholders onboard for a new platform that boosts your affiliate channel Platform Pick 2: Create a Checklist Learn how to break down your affiliate platform integration into manageable tasks with our checklist, keeping track of progress and staying on schedule. Platform Pick 3: Create a Feature Comparison Table Learn how to create a feature comparison table for affiliate platform selection. Prioritize, add KO factors, and use our prefilled example to get started! Platform Pick 4: Defining Your Needs Clearly Learn how to clearly define your business and needs for an affiliate platform. Use our guide to create a clear, detailed document for vendor discussions. Platform Pick 5: Hunt for the Right Platform Learn how to build a longlist of potential affiliate platforms. Use our guide to gather, filter, and organize options for your platform search. Platform Pick 6: Send Out Requests for Proposals Learn how to craft the perfect outreach email to vendors. Set expectations, request demos, and keep things organized for a smooth platform selection process. Platform Pick 7: Demos with Vendors Get the most out of vendor demos with this guide! Learn how to schedule, prepare, and evaluate platforms to find the perfect match for your needs. Platform Pick 8: Check Pricing and Value Learn how to evaluate pricing and value for affiliate platforms to make sure you're getting the best deal for your business now and in the future. Platform Pick 9: Choose Your Top Favorites Learn how to narrow down affiliate platforms by evaluating features, pricing, and scalability to choose the right fit for your business. Platform Pick 10: Business, Legal, and IT Prep Ensure your top affiliate platform meets business, legal, and technical needs by getting expert feedback and aligning with your teams before moving forward. Platform Pick 11: Integrate and Test it Learn how to track affiliate clicks and leads accurately, handle cookie consent, and ensure proper attribution for smooth affiliate marketing success. Platform Pick 12: Rollout Ensure a smooth affiliate platform rollout by reviewing tasks, coordinating teams, and monitoring post-launch performance for a seamless experience. #### Platform Pick: How to choose the right Affiliate Platform The Ultimate Affiliate Platform Guide We know it’s not easy. Choosing the right affiliate platform can feel overwhelming – too many options and too much at stake. That’s why we created the Platform Pick series: to guide you through each step with clarity and confidence. No buzzwords, no bias – just practical insights from people who’ve been there before. As consultants, we’ve helped dozens of companies find the right platform for their needs, and we know what really works (and what doesn’t). Inside you will find how to map your current setup and pain points, win stakeholder buy in, build vendor scorecards, and run focused demos. Inside you will find checklists, a feature comparison table, RFP and email templates, and a rollout plan that covers security, data protection, integrations, migration, testing, and training. The goal is simple. Help you choose with confidence and implement without drama. Platform Pick 1: Win Stakeholder SupportPlatform Pick 2: Create a ChecklistPlatform Pick 3: Create a Feature Comparison TablePlatform Pick 4: Define Your Needs ClearlyPlatform Pick 5: Hunt for the Right PlatformPlatform Pick 6: Send Out Requests for ProposalsPlatform Pick 7: Demos with VendorsPlatform Pick 8: Check Pricing and ValuePlatform Pick 9: Choose Your Top FavoritesPlatform Pick 10: Business, Legal, and IT PrepPlatform Pick 11: Integrate and Test itPlatform Pick 12: Rollout Ready? Let’s dive in. The Affiliate Platform Guide In a rush and want everything in one place? Download the complete guide to choosing the right affiliate platform and keep it as your handy reference. Download ebook #### Promo code tracking – not only for influencers Promo code tracking – not only for influencers Looking to collaborate with advertisers without broadcasting that you’re earning commissions through affiliate cooperation? Or maybe your platform isn’t too keen on affiliate links, or your followers just aren’t fans of them? That’s where promo codes come into play. With our system, you don’t need visible affiliate links. Get your personal promo code, and when someone uses it, that success is linked right back to you (even if your competitor tries to use it) No cookie tracking is needed. Our promo codes sidestep the usual cookie issues, ensuring your traffic is always tracked. #### Protect Your Brand with Our Safety Rules Protect Your Brand with Our Safety Rules Knowing where your traffic originates from is essential. With Paldock gain a comprehensive insight into the delivered traffic, tracing back to the specific pages and websites it’s coming from. Not only that. You have the power to allow or disallow specific domains. So if a site doesn’t align with your brand’s values or raises concerns, you can swiftly block it. Or the other way around, you can accept traffic only from allowed domains. #### Release notes 2025/12/17 Lead rejection & processing More flexible lead rejection: based on validation rules, filters, or pingtree sales results, by source (iframe, API) or by partner (include / exclude). It is now possible to process a lead even if it was reported as rejected to the affiliate (useful with iframes, where it’s better to show the user something). This can be driven by rejection on validation, filters or pingtree sale results. See more here. External final page Support for external final page:Affiliates can display pingtree results on their own side, either via API or via query parameters. See more here. Updated Affiliate API documentation All of the features above are now reflected in the Affiliate API documentation. We’ve also added per-field form validation, so your affiliates can validate each field as soon as the visitor fills it in, instead of validating everything only after the form is submitted. Form behaviour options You can now allow or block: Form prefill – ability to prefill fields from query parameters. Affiliate ID rewrite – ability to overwrite the form’s affiliate ID from a query parameter. Auto submit – automatically submit the form if all required fields are filled. Commissions In the commission list, an AutoApprove icon (⚡) was added to make auto-approve commissions easier to spot. Improved quick editing of commission amounts, with the option to set a commission as inactive (🚫). New transaction type: Prospect New native transaction type Prospect. The incoming lead keeps the name Lead. The lead sent to the advertiser is tracked as Prospect. Prospects can be filtered in reports. See more here. Reporting & logs Better filtering and sorting in reports and logs, including: ability to use two filters of the same type (e.g. in X find Y AND Z), numeric filters (e.g. show only days where the number of leads is higher than X), cross-report filtering across Affiliate / Advertiser / Offer – for example, filtering by affiliate inside an Offer report. Clearer tables: improved layout, column widths and horizontal scrolling. Added External ID and Event ID (1…n) to the lead log. Integration logs now include seconds in timestamps to make it clearer how long selling a lead actually takes. Advertiser report Added a dedicated Advertiser report to consolidate results per advertiser (whether they own an Offer or a channel). In this report, Clicks and Leads are only shown for entry Offers (not for channels). #### Release notes 2025/12/19 Categorization We added country-based categorization. You can now categorize offers, integrations, and other items by a specific country, or keep them global across all markets. Deep link We also introduced deep linking. You can attach a destination parameter to your offer link to send visitors directly to a specific page (product, landing page, application form, etc.) instead of a generic homepage. Each deep link automatically includes affiliate tracking parameters, so clicks and conversions remain correctly attributed with full reporting in PalDock. Learn more here. #### Release notes 2026/02/27 New Integration builder After months of work, our Integration Builder has a fresh new look and a lot more power. We redesigned it to be easier to use, more consistent across the whole system, and ready for more complex integrations. You will now see the same builder experience across Integrations, Tracking, Structures, and Feeds. Learn more in our Wiki. Built for flexibility Customers already praise PalDock for having the most flexible builders on the market, letting you integrate almost any API from an advertiser, affiliate partner, or external service. This update takes that flexibility further, while making it simpler to build and maintain your flows. Easier to build, easier to understand Instead of the old table view, we introduced a node based editor where you connect nodes into clear flows based on your needs. Think of it as a Make or Zapier style builder tailored for lead generation, without paying per node run. New capabilities Webhook – Accept external requests and events, for example a signal that a lead is ready to be polled, or a direct status update. Wait – Pause a flow and run a branch again later. Break – Stop repeating a branch after X attempts. HTTP signatures – Support for a wide range of signature methods to match virtually any advertiser or service requirements. Subscenario – Call a scenario inside another scenario so you can reuse logic and avoid duplication. Mirror – Reference another node instead of duplicating it, keeping your flows cleaner and easier to maintain. Enjoy! #### Release notes 2026/04/30 Based on your feedback, we’ve pushed the Integration Builder even further. We’ve rolled out a massive wave of UX fixes and performance updates. Here’s the breakdown of the most important changes: Advanced Integration Builder Flexible Webhooks: Added the option to delay Pingtree for better flow management. Precision Parameter Picker: You can now select in the parameter picker a specific outputs from specific steps, giving you surgical precision over your data. Fully Redesigned Logs We’ve rebuilt the logging system from the ground up for maximum transparency: Categorized Logs: Separate views for Integration, Structure, and Tracking. Granular Tracking: Detailed logs for every single step of the process. Action Insights: Deep-dive details for every action performed within the system. Additional Features Transaction Context: We are now attaching the source (lead/click) directly to transactions, including all submitted data (like form inputs). Affiliate Postback Self-Service: Affiliates can now create their own postbacks independently. No more waiting for admin manual setup. Domain Management: A much simpler interface for managing your custom domains. #### Release notes 2026/06/30 We implemented numerous performance improvements and feature enhancements based on your feedback. We also significantly expanded the flexibility of the following features: External Final Page The External Final Page feature has been completely redesigned to provide much greater flexibility for comparison websites and custom integrations, allowing you to move the entire loading and results (offer wall) experience to your own platform and show results in your own design and user flow. The update includes a default final page, partner-specific overrides, configurable redirect behavior, and extended Affiliate API support. Added Default External Final Page support, including automatic lead data and system parameters. Added partner permissions for External Final Page Override & Detailed Response. Added partner restrictions for Default External Final Page usage. Added Skip internal loader and redirect immediately option. Added Include results in redirect option to enable or disable query parameters during redirects. Extended the Affiliate API to support external_redirect_url and external_redirect_results for authorized affiliates, allowing request-level overrides of the default configuration. See the full details and integration guide in our Knowledge Base article for External Final Page. Gross Clicks Gross click tracking has been improved by deduplicating clicks from the same visitor within a one-hour window, resulting in more accurate traffic and performance statistics. Conversion Pixels & SPA Conversion pixel tracking has been enhanced to fully support Single Page Applications (SPA), allowing multiple pixel instances on the same page, custom tracking cookies, and more reliable tracking in modern JavaScript applications. Added support for running multiple conversion pixel instances on the same page, improving compatibility with Single Page Applications (SPA). Introduced additional SPA improvements, including support for custom tracking cookies via pcidCookie and optional fallback to the default PalDock cookie using pcidCookieFallback, making custom tracking implementations easier to integrate. PingTree & Lead Log Lead rejection diagnostics have been significantly improved with more granular reject reasons and support for custom rejection messages returned by integrations, making troubleshooting much easier for both administrators and partners. Added more granular reject reasons in both the PingTree and Lead Log, making it easier to understand why a lead was rejected. Integrations can now return a custom reject reason, which is displayed directly in PalDock for easier debugging and troubleshooting. #### Release notes 2026/07/31 What’s new in PalDock? A lot of this month went into things you won’t see directly – query optimisation, indexing, and general tuning under the hood. The app should simply feel faster, especially on bigger data ranges. But there’s plenty visible too: Multi-currency support PalDock now works in more than one currency. Set a currency per workspace, affiliate or advertiser — and affiliates and advertisers get their own settings area to pick the currency their balances show in. Changing your tenant’s main currency converts all your historical data with it. The conversion runs in the background without slowing anything down, and your reports tell you when it’s in progress. Exchange rates update daily on their own. Better pingtree visibility The pingtree log shows how long each channel took in milliseconds, and tells you why a step failed. You can filter and sort by duration to find slow channels. Integrations HMAC SHA-256 and SHA-512 signatures for JSON HTTP steps DOT delimiter support in mapping Typing in a modify step’s field adds {} automatically #### Release notes 2026/08/14 This was a big one. We went through roughly 200 pages of our knowledge base and rewrote the whole thing. Clearer structure, consistent terminology, and every feature covered properly. But the real change is what you can now do with it. The entire documentation is available as AI-ready Markdown. Add the links below as sources or knowledge in your AI tool, whether that’s a Claude Project, a ChatGPT custom GPT, a Gemini Gem, or anything else you use. Your assistant can then answer PalDock questions, walk you through configuration and help you build integrations with the actual documentation in front of it instead of guessing. It comes in two files, split because of the sheer volume: Knowledge Base: how to use and configure the PalDock app. Integrations and Integration knowhow – focused on dozens of integrations, including API documentation, PalDock blueprints, and our integration know-how. This allows your AI assistant to create and manage integrations. We recommend creating a dedicated project in your AI chat rather than dropping them into a single chat, since the documentation is large and most tools have limited context per project. The same data also powers our own in-app chat, which got noticeably better in the process. So if you’d rather just ask on the spot, it can now help you with configuration and integrations too. #### Scale your business and start your own Affiliate program Scale your business and start your own Affiliate program Thinking big? Considering running your own affiliate program or even an entire network in the future? It’s crucial to pick a platform that not only offers the features we’ve covered before but also empowers you to oversee your very own affiliates. Dive into recruiting, customize commission rates or tiers, and explore many more possibilities. Set your sights on scaling up with the right tools in hand so you don’t have to difficultly change them later. #### Track accurately affiliate or any other traffic and conversions Track accurately affiliate or any other traffic and conversions Track traffic from your affiliates and any of your campaigns seamlessly. Set clear attribution rules to avoid double-paying for a single conversion. Prefer your paid campaign to take precedence over affiliate sources? We’ve got you covered. Use either cookie-based, cookie-less tracking or promo codes for transparent and fair conversion attribution. View all your traffic and campaign data, not just affiliate insights, in a unified dashboard. Networks can also define their attribution rules—whether prioritizing their own sources over affiliates or opting for last-click attribution and can view all traffic, conversions, and campaign data in a unified dashboard across all partners, advertisers and their own campaigns. #### Tracking even without URL parameters Tracking even without URL parameters Similarly, you can monitor traffic from your website without using the affiliate URL tags. Affiliates opt for this when working with display ad networks, which have tight rules against affiliate collaborations. With Paldock, the process is a breeze. Just register your domain, add a tracking script, and we’ll do the rest. Your traffic gets tracked and attributed to you, even without URL parameters. The best part? It’s entirely cookie-independent! No worries about missed tracking due to cookie restrictions. #### URL shortener URL shortener If you are already using any of the available tools for creating shortened branded links you probably know that using and managing direct links is hell. If you are not using a similar tool yet, start now! Before you experience the horror of: changing the link on numerous locations and forgetting some setting up redirect type, (no)follow on individual links instead of in bulk having your visitors be afraid to click on link not measuring the clicks and not noticing changes or errors – be it yours or of destination website’s and more And when deciding what tool to use, you will check whether the tool offers:  categorization and tagging redirect and destination URL uptime monitoring parameter forwarding click and conversion tracking reporting In Paldock, we say YES to all of those And we say YES to much more since we are not only a link management platform. We know how nasty it is to pick a tool that seemingly satisfies your current needs to find out half a year later, that you need one more tool to scale your business.  We have been there and it’s one of the reasons the Paldock was created – to offer not only the basic features from one segment (link management, campaign tracking, offer tracking, affiliate management, lead forms, API and lead routing) but to combine them in a way that supports your growth! We got you covered! Are you a webmaster who just needs to manage branded links from one place? We got you covered! Have you started to buy traffic from different sources and you need to know where does it convert, what you paid and earned, and if you have a profit? We got you covered! Do you want to later buy traffic from affiliates and manage affiliates and offers in one place? Do you want to later use iframes or custom forms to collect your own leads and sell them through API to advertisers? Do you want to sell the leads in a sophisticated way through various distribution types? You guessed it, we got you covered too! All of this together with great reports visualizing your profits in an easy way. Our URL shortener is for all of those, who: want to see all data from links in clear and user-friendly charts and statistics want to add a clickID for each click sent to Advertiser in order to know which specific click converted want to set capping on clicks to send the exact amount of clicks that your Advertiser paid? And if exceeded, to show a different URL want to set expiration on links and if expired, show a different URL want to automatically check if the destination URL is up and running and if not, show a different URL want to set custom URL parameters and forward them for example to use Google ClientID as a ClickID and get even deeper analysis want to set remarketing pixel for each redirected click want to NOT GET CRAZY from hundreds of uncategorized, untagged links ### Pages #### (No Title) Let’s Talk Share your goals, blockers, and current setup with us. We will help you evaluate your options and recommend the most practical next steps. #### About us Based on real Affiliate Marketing Experience The name PalDock comes from our goal of helping partners (pals) dock with advertisers and creating a reliable harbor for cooperation. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → About us Since 2014, we’ve been dedicated to helping companies maximize their affiliate marketing efforts by providing expert advice on key focus areas and potential pitfalls to avoid. Through our extensive experience, we’ve encountered common challenges, especially with large programs on networks, that could have been mitigated with the right affiliate solutions. In response to these challenges, we began developing our affiliate software in 2020, aiming to become a leader in the field. Originally designed as an internal tool for us and our clients, its success has led us to make it available to everyone. Our Mission Our mission is to simplify running an online business for partners and advertisers, maximizing revenue and growth. Our Vission We aim to provide an all-in-one affiliate marketing solution that streamlines the promotion and growth process for partners, enabling advertisers to effortlessly scale their affiliate programs to maximize revenues. Understanding the Challenges At PalDock, we understand the challenges online businesses face in leveraging affiliate marketing and lead generation to reach their target audience. With over a decade years of experience, our team has helped companies fully utilize affiliate marketing. However, we frequently encountered the same blockers, leading our clients to seek a comprehensive solution that combines affiliate marketing with lead generation – a service not offered by existing SaaS tools. Many resorted to custom-built solutions, which only created additional issues. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. The Need for One Platform As our clients acquired all available affiliates in their industries, they discovered that starting an affiliate or lead generation business was incredibly challenging, often requiring dozens of incompatible or inadequate tools for managing links, measuring clicks, generating leads, tracking conversions, measuring commissions, and aggregating up-to-date product data. When affiliates manage multiple websites, this complexity increases for both advertisers and affiliates, underscoring the need for consolidated marketing tools and streamlined product data. To address these issues, we created PalDock, a unique tool that combines all essential features based on our 10+ years of industry experience. PalDock is designed to simplify online business for publishers and their advertisers, empowering them to achieve greater success in their affiliate marketing efforts. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → #### Affiliate program URL: https://paldock.com/affiliate-program/ #### Affiliate Software for Loans Affiliate software for Loans Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Key Features to Look for in Lending Affiliate Software Running a loan company with services like payday loans, consumer loans or other kinds of loans? Thinking about diving into affiliate marketing? You’ll need a tool that does more than the basics – one that’s packed with advanced features just for your industry. You’re probably here for the advanced stuff, right? We’ll skip the basics then. But hey, if you wanna peek at those too, they’re all listed below. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free In mature lending markets, 90% of new loans come via affiliate APIs Not having an affiliate API or anything close to this scale? You are missing out. With PalDock, you get the features to outgrow competitors and get more loans from affiliates. Track Cookie-less Tracking Tracking might sound basic, but in lending it is anything but. Cookie tracking fails because loans are rarely approved instantly. Clients often need verification or a follow-up which makes cookie-based tracking unreliable. That is why PalDock combines cookie and cookie-less tracking to deliver the highest level of accuracy. Every conversion is counted even when the process takes longer. Manage Lead Generators and Brokers In your business working with lead generators and brokers is not optional. They drive the highest volumes and without them you are leaving money on the table. The problem is that classic affiliate software was not built for them. They need API integrations, iframe forms and advanced lead handling features that most platforms do not offer. This is why we built PalDock. It is the only tool that combines affiliate tracking and lead generation in one platform so you never miss out on your biggest partners and never need to switch later. Validate Lead structures and validations With PalDock you can create any lead structure for any product, from full applications to abandoned forms, and run them all side by side to maximize the value. Advanced validation ensures fake or low quality leads are rejected. Everything is built in so you just plug it in and start. PalDock keeps data clean and user friendly without extra coding. You can set precise validation rules, guide users with smart input formatting, reduce errors through automatic calculations and instantly verify emails, phone numbers or anything else through external validations. The result is simple: only high quality leads and no wasted time or payouts. Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Embed Embedded forms Affiliate links are easy, but they are far less effective than processing customers directly through forms. By embedding fully customizable forms or banners on their websites, affiliates capture higher intent, improve conversion rates and ultimately drive more revenue. Instead of losing potential customers in extra clicks, the entire process happens seamlessly inside the form. Even affiliates with no technical knowledge can simply copy and paste the embed code, customize the look and start sending leads immediately. For those who need more control, PalDock also provides a powerful API. Integrate API integrations Lead generators and brokers have very different requirements. Lead generators usually only need a simple API to register a lead, get the result and redirect the user, with an optional precheck method for auctions and bidding to confirm your interest before the lead is registered. Brokers, on the other hand, expect the entire process to happen on their side from verification to processing. Your API must do more than just accept lead data. It has to return prefilled contracts, pricing lists, verification triggers, processing steps and results. PalDock was built to handle all of it. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Evaluate Reporting The best part is that PalDock lets you track both clicks and lead performance seamlessly in one place. No more juggling two tools or wasting time on custom setups. All parties get access to a real time dashboard where they can see and verify data, which brings full transparency and eliminates the need for sending Excel files back and forth. PalDock also provides a dedicated reject reason report so affiliates can analyze and optimize their campaigns to deliver better quality leads. With a clear, organized view of all affiliate traffic and lead data together, you can focus on growth. Payouts Consolidate invoices With PalDock you can consolidate all affiliate invoices into a single one and even have it paid early through our factoring partner. This means you improve cashflow, extend payment terms and unlock funds you can reinvest immediately to grow your revenue. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free Already have a custom tool? You are probably missing out. If you answered YES to at least half of these questions, you’re missing proper affiliate software that could unlock your business growth. Are you missing a unified real time view of affiliate and leadgen conversions across links, embeddable forms, and API? Do you still send affiliate performance reports manually once a month? Do affiliates lack a live dashboard with transparent metrics and payouts? Do your affiliates see different lead counts than you do? Is onboarding new affiliates slow or difficult? Do your affiliates need a developer and days or weeks of testing and debugging to integrate your API, pulling your IT into support? Are lead rejection reasons not shared with partners in real time? Do you handle lead validation inside your codebase and need IT work to add new checks? Do you lack embeddable forms for partners who cannot integrate via API? Do you have no workflow to resell rejected leads to secondary buyers for cost recovery? Do you lack automatically calculated affiliate balances to verify payouts and prevent duplicate payouts? Is your current setup hard to scale to more countries and many more partners? Does maintaining and enhancing your custom affiliate tool drain IT resources that should focus on core business? PalDock solves all these issues and many more! We eliminate the headache of custom development while outperforming other solutions on the market. Why Choose PalDock over Others?See How We Compare! Best Tune AlternativeBest CAKE AlternativeBest Post Affiliate Pro AlternativeBest Affise AlternativeBest Tapfiliate AlternativeBest Phonexa AlternativeBets MyAffiliates AlternativeBest LeadDyno AlternativeBest Affilbox Alternative Best Voluum AlternativeBest Trackier AlternativeBest RedTrack AlternativeBest Partnerstack AlternativeBest AffiliateWP AlternativeBest Rewardful AlternativeBest Scaleo AlternativeBest Uppromote AlternativeBest Refersion Alternative Best Everflow AlternativeBest FunnelFlux Pro AlternativeBest Binom AlternativeBest FirstPromoter AlternativeBest WP Affiliate AlternativeBest Solid Affiliate AlternativeBest Kiflo AlternativeBest Partnerize AlternativeBest Impact AlternativeBest Plat Alternative Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features #### Affiliate Software for Telco Affiliate software for Telco Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Key Features to Look for in Software for Telco The right platform should make it easy set flexible commission structures, adjust payouts for canceled services and track every link with precision. To take your program further, you also need advanced features such as cookie-less conversion tracking, aggregated product feeds that keep affiliates updated on current tariffs or deals, API-driven promotions like availability checks, and built-in lead generation tools to capture new clients. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free Track Cookie-less Tracking Tracking might sound basic, but in telco it quickly becomes complex. Cookie tracking fails when orders are not approved instantly or when the product is processed through a call center. Clients often need verification or a follow-up, which makes cookie-based tracking unreliable. That is why PalDock combines cookie and cookieless tracking to deliver the highest level of accuracy. Every conversion is counted, even when the process takes longer. Optimize Custom commission structures Tailor your commission structures to fit any model you need, including custom formulas. In the telco industry, an end customer might buy directly online through self-service or via a call center, each with its own cost implications. A self-service product purchase could reward the affiliate with a multiple of the monthly product value, while a lead completed through customer service could be adjusted to account for support costs. On top of that, you can boost motivation with one-time or automated bonuses and apply penalties when needed, giving you full flexibility to optimize partner performance. Aggregate Commission adjustments It is smart to set penalties for early cancellations so affiliates are rewarded only for real, lasting sales. Penalties can be a fixed fee, the full commission originally paid, or an amount adjusted based on how long the customer stayed before canceling. This way, you protect your revenue while keeping the commission model fair for everyone. Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Generate Always-Up-To-Date Assets Take full control over your marketing assets with easy management of expiration dates and post-expiration content. Say goodbye to outdated banners or information on affiliate sites. Affiliates can enjoy the benefits of auto-updating HTML banners or tap into real-time product feeds- perfect for comparison websites, such as comparison of phone deals or mobile tariffs. Build Build your own product Sending clicks to advertisers is decent, but let’s face it, it’s like throwing darts in the dark. You can’t really steer the conversion once it’s on their website. Here’s where Lead Generation shines. Instead of just routing clicks with unpredictable outcomes, why not gather leads and orders directly on your site and pass on this valuable data? It’s a win-win-win! Your visitors get extra value, you grow a robust database, and essentially, you’re crafting your very own product and the Advertiser is happy for a hot lead. The result? A significant revenue increase, as a solid lead far outvalues a mere redirect. Plus you get an edge over your competitors with your own product. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Evaluate Reporting The best part is that PalDock lets you track both clicks and lead performance seamlessly in one place. No more juggling two tools or wasting time on custom setups. All parties get access to a real time dashboard where they can see and verify data, which brings full transparency and eliminates the need for sending Excel files back and forth. Start your own Affiliate program Thinking big? Considering running your own affiliate program in the future? Dive into recruiting partners, customize commission rates or tiers, and explore many more possibilities. Set your sights on scaling up with the right tools in hand. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features #### AffiliateWP Alternative What is AffiliateWP? AffiliateWP is a WordPress plugin built for site owners who want to add a basic affiliate program to their site. The appeal is clear: installation is quick, it lives inside your WordPress dashboard and pricing looks reasonable at first glance. But AffiliateWP is not a true affiliate platform. It only works in WordPress, the feature set is limited to basic referral tracking and payouts, and almost everything beyond that depends on extra add-ons or custom development. Many users also complain that performance drops as databases grow and that support for complex commission rules is very thin. For a small WordPress shop that just wants a lightweight referral plugin, AffiliateWP can get the job done. For any serious affiliate or lead-gen operation that requires more, it simply does not compare. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → AffiliateWP vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: AffiliateWPPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Affilbox Alternative What is AffilBox? AffilBox is mainly used by e-shops in the local market. Its appeal is the low entry cost and simple setup in Czech language. However, its functionality might be limited compared to modern platforms. AffilBox focuses almost entirely on link tracking and banners, with no built-in lead management, validation, reject reason reporting and basic reporting. It also lacks proper integrations outside of the Czech ecosystem, making it difficult for companies that want to grow internationally. For anything beyond a basic affiliate program with a few partners, AffilBox quickly shows its limits. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → AffilBox vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: AffilBoxPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Affise alternative What is Affise? Affise is a newer SaaS-based affiliate tracking platform that grew quickly thanks to its modern UI and competitive pricing. It is strong on the basics of affiliate link tracking, partner management, and reporting, which makes it popular with ad networks and agencies. But when it comes to more complex workflows, users often run into limitations. Lead generation is not a native focus and there are no embedded forms, no built-in lead validation, and handling multiple lead structures requires external tools. Reporting can feel fragmented, and features like reject-reason transparency or invoice consolidation are missing. Affise also tends to segment functionality into different tiers, so advanced features are gated behind higher plans, and scaling up often comes with a steep price jump. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Affise vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: AffisePalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best CAKE alternative What is CAKE? CAKE (often called GetCake) has been on the market for over a decade, and the age shows in its UX. It is a solid platform, but the interface feels dated, workflows require too many steps, and many customizations still need technical support. Users often highlight missing features such as built-in lead validation, support for multiple lead structures, and full transparency around rejected leads. CAKE also charges separately for Affiliate Marketing and Lead Distribution, which means covering both requires essentially two products instead of one unified solution. Pricing is less transparent than newer SaaS tools, with enterprise-style contracts and onboarding fees still the norm. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → CAKE vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: CAKEPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best LeadDyno Alternative What is LeadDyno? LeadDyno is one of the simplest affiliate tools on the market, mainly used by very small e-commerce shops or startups because it is cheap and easy to plug into Shopify or Stripe. Beyond that, it practically cannot do anything. There is no real lead management, no validation, no handling of multiple commission structures, no advanced reporting and almost no flexibility once you want to scale. The interface feels outdated and many users quickly outgrow the tool once they try to run more than a very basic referral program. For a hobby project or a single-store referral program, LeadDyno can be enough. But for any serious business that needs more it simply does not deliver. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → LeadDyno vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: LeadDynoPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best MyAffiliates Alternative What is MyAffiliates? MyAffiliates is a long-standing affiliate software best known in the iGaming sector. It is often chosen by casinos and betting companies because it can handle large volumes of affiliates and has flexible commission settings. However, the platform shows its age in several areas. The user interface is dated, reporting can be slow, and many workflows feel heavy and complex. There is no native lead management, limited transparency around rejected conversions, and the setup often requires significant support from their team. Pricing is structured more like enterprise software which can make it less attractive for mid-sized operators or companies outside of iGaming. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → MyAffiliates vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: MyAffiliatesPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Post Affiliate Pro Alternative What is Post Affiliate Pro? Post Affiliate Pro is one of the oldest affiliate tracking tools on the market, and it still attracts small businesses because of its low entry price. However, the platform shows its limitations quickly. The interface feels outdated, reporting is slow on larger datasets, and the feature set is narrowly focused on link and banner tracking. There is no native lead management, no built-in validation, and limited flexibility in handling complex commission models. Many users also point out that while setup looks simple at first, ongoing maintenance requires technical workarounds and manual adjustments. Support and documentation are not always on par with enterprise-grade solutions, making it feel more like a budget option than a modern affiliate and leadgen platform. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Post Affiliate Pro vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: Post Affiliate ProPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best RedTrack Alternative What is RedTrack? RedTrack grew out of the need for a cheaper and simpler alternative to Voluum and quickly carved out a space among solo affiliates and mid-sized media buying teams. Its strengths lie in campaign attribution, budget control and publisher management for paid traffic. The interface is lightweight and generally faster than some older trackers, and the pricing is often highlighted as more accessible. Where users get stuck is when they want to move beyond campaign tracking. RedTrack does not provide proper affiliate or lead generation features and fraud detection is limited compared to enterprise solutions. Complex commission structures or multi-stage conversions cannot be modeled inside the platform, which makes it unsuitable for verticals like finance or iGaming. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → RedTrack vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: RedTrackPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Tapfiliate Alternative What is Tapfiliate? Tapfiliate is positioned as a lightweight affiliate tracking tool aimed mostly at SaaS startups, e-commerce brands and creators. It has a clean interface, easy onboarding and simple referral program templates which makes it appealing for small teams getting started with affiliate marketing. However, the simplicity is also its main limitation. Tapfiliate focuses almost entirely on link and referral tracking with no built-in lead management, no validation, and no ability to support multiple lead structures or complex commission logic. Reporting is basic, integrations are limited compared to enterprise platforms and scaling programs beyond a few partners quickly becomes a challenge. For small e-commerce stores or SaaS startups that only need basic referral tracking, Tapfiliate can be a quick solution. But for businesses that need robust affiliate and leadgen capabilities, advanced validation, reject-reason reporting, embedded forms, cookieless tracking and unified financial handling, Tapfiliate falls short and that is where PalDock stands out as the more complete alternative. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Tapfiliate vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: TapfiliatePalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Trackdesk Alternative What is TrackDesk? TrackDesk targets small to mid-sized affiliate programs, especially DTC e-commerce brands, content/influencer campaigns, and agencies that need quick setup and clean partner workflows. Its strengths are simple offer/link/coupon management, easy partner onboarding, plug-and-play postbacks, a clear partner portal, and straightforward dashboards; integrations with common storefronts and payment tools make it fast to get live. It’s less suited to heavy lead-gen or enterprise scenarios that need granular lead validation/routing, complex or hybrid commission engines, multi-touch attribution, or deep BI with custom event schemas. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → TrackDesk vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: TrackDeskPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Trackier Alternative What is Trackier? Trackier positions itself as a performance marketing suite and is widely adopted by ad networks across India, Southeast Asia and the Middle East. It appeals to users with aggressive pricing, mobile attribution add-ons and integrations with local traffic sources. Where criticism comes in is consistency. The dashboard looks modern but the UX is patchy, with common complaints about confusing navigation and frequent bugs. Reporting is adequate for click campaigns, yet lacks depth for fraud analysis or long-cycle conversions. Lead distribution is absent, validation tools are missing, and financial reconciliation still has to be handled outside the system. Customer support is another weak spot, with response times varying heavily depending on your plan. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Trackier vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: TrackierPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Tune (HasOffers) alternative What is Tune? TUNE is a mature affiliate tracking platform and many agencies and enterprises rely on it for links, postbacks, and reporting. Where teams begin to struggle is anything beyond classic link tracking. TUNE Users also flag day-to-day frictions such as difficulty setting different payouts by country and even the inability to export some reports to Excel, plus general UX friction like frequent screen-switching. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Tune vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: TunePalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Best Voluum Alternative What is Voluum? Voluum is an ad tracking platform that grew popular among media buyers and performance marketers because of its fast click tracking, detailed reporting and traffic distribution features. It is well suited for solo affiliates or agencies running paid ads across multiple channels. However, it is not designed to be a full affiliate software. Voluum does not include any advanced affiliate features or lead handling. Commission structures are limited and the tool is focused almost entirely on click and conversion tracking rather than managing partners or running complex affiliate programs. Many users also point out that costs rise quickly with traffic volume. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Voluum vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: Voluum PalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Binom Alternative What is Binom? Binom is one of the oldest self-hosted affiliate trackers, known for its speed and reliability, but it feels outdated by today’s standards. The interface and setup process belong to another era, and maintaining your own server adds unnecessary friction. It handles click and conversion tracking well, yet lacks modern integrations, APIs, and workflow automation that most teams expect today. For solo affiliates who value full control and don’t mind dealing with servers, Binom can still work, but for growing teams it is a dead end. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Binom vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: BinomPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Blog URL: https://paldock.com/blog/ #### Broker PalDock’s use cases for Brokers Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro Running and scaling a Brokerage operation is no easy task, especially when every vertical has its own demands. Working with product comparisons? Clean feeds and real-time API integrations are essential. Managing lead delivery? Links, embeddable forms, and APIs all need to track flawlessly.Launching new verticals? You’ll want forms, integrations, and postbacks you can set up in minutes, not after weeks of IT debugging. Everything you need in one place We dive deep into understanding what you need, crafting Paldock as the go-to solution for all things related to Affiliate marketing and running a Network. We’ve got tools and features to support your activities. Let’s break down what we offer, from the simple stuff to the more advanced. Ready? Here’s what’s on deck: Accurately track in-house or affiliate traffic Bring your revenues back with Cookie-less tracking Track conversions and consolidate results Connect anything via API – no developers needed Boost revenues by Lead generation Automate Product Data with Advanced Aggregation Scale into the network to get affiliate traffic Efficiently Manage Your Partners Track Track affiliate or in-house traffic and conversions accurately Whether it’s from affiliates or your own campaigns, monitor all traffic effortlessly. Define your attribution rules—whether prioritizing your own sources over affiliates or opting for a last-click attribution. Use cookie-based and cookie-less tracking, or utilize promo codes for clear and fair conversion tracking. View all traffic, conversions, and campaign data in a unified dashboard across all partners, advertisers, and your own campaigns. Manage Efficiently Manage Your Partners Start strong with smooth recruitment and onboarding of affiliates or advertisers, then categorize, tag, and allocate dedicated managers to ensure personalized handling. Customize commission plans – be it CPA, CPS, revenue sharing, or any other model (including custom formulas). You can also set distinct commission models for partners and advertisers. Keep the motivation high with occasional bonuses or go for regular, automated incentives. And if there’s a slip-up, there are penalties in place.  Effortless Link Management Juggling multiple affiliate links or websites? Things can get tangled fast. That’s where Paldock steps in. Centralize and manage all your affiliate links from a single hub, eliminating the hassle of going through countless posts or sites to make link updates. But we don’t stop there. We actively monitor link health, ensuring users are smoothly redirected to an alternative you’ve set up if a link breaks. And, of course, we’ll promptly notify you.  Bring your revenues back with Cookie-less tracking Did you know? Up to 64 percent of global consumers agree that they accept all cookie permissions when prompted but rates vary by region according to YouGov’s global consumer study. If your advertiser relies solely on cookies, that’s a whopping 40% of potential revenues slipping away from you. But Paldock has a solution. With our Postback tracking, we bypass cookies altogether, ensuring every conversion and every cent is captured. PalDock ensures every possible dollar lands in your pocket. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Track Connect anything via API – no developers needed Lead generators and brokers have very different requirements. Lead generators usually only need a simple API to register a lead, get the result and redirect the user, with an optional precheck method for auctions and bidding to confirm your interest before the lead is registered. Brokers, on the other hand, expect the entire process to happen on their side from verification to processing. The API must do more than just accept lead data. It has to return prefilled contracts, pricing lists, verification triggers, processing steps and results. PalDock was built to handle all of it. Manage Boost revenues by Lead generation Think beyond just clicks! Dive into leads as a powerful traffic source and track everything on a single, unified platform. Make the process more efficient: equip affiliates with ready-to-embed customizable forms for their sites or an API for direct lead submissions to Paldock, and, ultimately, to you. Craft the perfect lead journey with our intuitive drag-and-drop editor, packed with lead validation, verification, and advanced filtering. Bonus: If your affiliate is already on Paldock, you’re in for a smooth setup, potentially saving weeks of API integration time. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Use various lead distribution methods Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Earn maximum revenue thanks to smart lead distribution methods. Whatever you envision, we’ve got the tools. Integrate with Advertisers via API, gather all the essential data, and turn those connections to your advantage. Automate Product Data with Advanced Aggregation Product comparison is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds including your own for easy comparison on your sites. The best part? Updates sync automatically with advertiser XML changes, but you also have the flexibility to tweak things manually.  Dominate Your Industry with Our Unique Features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free #### Career Work with us! Welcome to PalDock, a Software as a Service based in Europe. Our Mission Our mission is to simplify running an online business for partners and advertisers with maximal revenue and growth. Our Vission To provide an all-in-one affiliate marketing solution, simplifying the process of promotion and growth for partners and enabling advertisers to effortlessly scale their affiliate programs to maximize revenues. Work from Home or Office The office is in the xPORT building, 15 minutes from the Prague City center. What is our stack? At Paldock, we utilize a modern and robust technical stack to power our platform. Our backend is built with PHP and Laravel, providing a solid foundation for our application. We also leverage React for our front end, allowing for a dynamic and responsive user interface. To ensure consistency and efficiency in our design, we use Tailwind CSS, a utility-first CSS framework. Additionally, we utilize Storybook to develop, test, and document our UI components, ensuring they are consistent and reusable across the platform. With this powerful technical stack, we are able to provide a seamless and reliable user experience for our partners and advertisers. Core values we embrace We value independence, encouraging our employees to work independently on projects and take ownership of their work. We also value a proactive attitude, where employees take the initiative to identify opportunities for growth and improvement. In addition to these core values, we value honesty, transparency, and integrity in all our interactions, both internally and with our clients. We believe that by upholding these values, we can build a culture of trust and mutual respect, and create a positive impact on our team, clients, and the community at large. Interested to join us? We are hiring! PHP Laravel Developer We are seeking a senior-level programmer with at least a few years of experience, specifically with PHP and the Laravel framework. Knowledge of React.js, Docker, and Git is a plus, but we understand that these skills can be learned on the job. React Typescript Developer We are seeking a senior-level programmer with at least a few years of experience, specifically with React (Typescript). Knowledge of Laravel, Docker, and Git is a plus, but we understand that these skills can be learned on the job. Automation Tester We are looking for a skilled Test Automation Engineer to join our team. You will be responsible for creating and executing automated tests to ensure the quality of our software products. Join us if you are passionate about delivering high-quality software and enjoy working in a fast-paced environment. What happens next? If you’re interested in working with us, we’d love to hear from you. Send us a message along with your profile (LinkedIn, StartupJobs, CV, etc.) and a brief introduction about yourself. If you apply for a developer position and have code samples you’re proud of, such as a personal GitHub profile, feel free to share them with us. If you apply for a business position, we would love to hear your feedback on our current image and areas of potential improvement. The interview process is fully online and will be conducted by Lukas, our founder. During the interview, we’ll be interested in hearing about your experience, skills, desire to learn, style and overall approach. We also want to know your goals, plans, and what you’re looking to avoid in your career. If you don’t have any work samples available, we won’t burden you with extra preparation. If we determine there’s a good fit, we’ll send you a binding offer of cooperation. We’re open to starting immediately or at a later date that works for you. We look forward to meeting you! #### Clickmeter alternative What is ClickMeter? ClickMeter is an old school link tracking tool that was quite handy back when you mainly needed to count clicks and monitor basic conversions. It lets you create tracking links, run A/B tests, watch referrers and see simple reports, but that is more or less where it stops. The interface feels dated, most features are built around plain link tracking rather than complex funnels or affiliate relationships, and it does not really keep up with modern needs like flexible APIs, lead level data or multi touch journeys. For simple campaigns or solo marketers it can still work, but for anyone running serious affiliate or lead generation operations it feels more like a legacy utility than a long term platform to grow on. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → ClickMeter vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: ClickMeterPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Best Clickmeter Alternative PalDock is more than just an alternative to Clickmeter. Enjoy better features, a great user experience, and a friendlier attitude with flexibility for custom solutions. No setup fee No credit card required Cancel anytime Clickmeter Pricing vs PalDock Compare Clickmeter costs with PalDock to find the best option for your needs ClickmeterPalDockTry alternativeTry for freePackage comparisonSolution also for AffiliatesEmbedded formsAPI for LeadsAuto Generating Banners PalDock has simple pricing and no-risk guarantee Partners Advertisers Networks Free $ 0 yes, it’s completely free! Cloak LinksCreate branded shortened links and manage them from one place Try for free Lite $ 9 per month billed annually or
$11 monthly billing Track LinksMeasure clicks in reports, categorize links, and set substitutes Try for free Plus $ 49 per month billed annually or $59 monthly billing Track offersTrack campaigns and conversions across all offers in one place Try for free Pro $ 129 per month billed annually or $139 monthly billing Basic Affiliate managementBest for creating a simple affiliate program for your business Try for free Ultimate $ 249 per month billed annually or $269monthly billing Advanced Affiliate managementIdeal for creating a more elaborate affiliate program Try for free Custom $ ? – CustomScale your marketing efforts with unlimited plan and custom features Try for free Network $ 599 per month billed annually or $699 monthly billing Manage affiliates and advertisersConnect Affiliates with Advertisers, set commissions, access, and rules Try for Free Leadgen $ 999 per month billed annually or $1099 monthly billing Run Lead generationCreate own product with API to Advertisers and other services Try for Free Custom $ ? – Grow to the moonScale your marketing efforts with unlimited plan and custom features Try for Free Dominate your industry with our unique features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Missing Some Features? Need a feature that’s missing? No worries! Just let us know, and we’ll work on implementing it for you. Contact Us Why Choose PalDock over Others?See How We Compare! Best Tune AlternativeBest CAKE AlternativeBest Post Affiliate Pro AlternativeBest Affise AlternativeBest Tapfiliate AlternativeBest Phonexa AlternativeBets MyAffiliates AlternativeBest LeadDyno AlternativeBest Affilbox Alternative Best Voluum AlternativeBest Trackier AlternativeBest RedTrack AlternativeBest Partnerstack AlternativeBest AffiliateWP AlternativeBest Rewardful AlternativeBest Scaleo AlternativeBest Uppromote AlternativeBest Refersion Alternative Best Everflow AlternativeBest FunnelFlux Pro AlternativeBest Binom AlternativeBest FirstPromoter AlternativeBest WP Affiliate AlternativeBest Solid Affiliate AlternativeBest Kiflo AlternativeBest Partnerize AlternativeBest Impact AlternativeBest Plat Alternative What Our Customers Say About PalDock We manage traffic through affiliate links and lead generation via API, and having both in one platform is a major advantage. With everything in a single dashboard, we gain full control of our affiliate channels and the flexibility to experiment and optimize more effectively. Since PalDock is designed for affiliates as well, integrating the standardized API is straightforward, allowing them to start sending leads within an hour. Simone BertoloneDirectorOrka Ventures As Affiliate Consultants, we’ve often seen clients struggle to start and grow their programs. We help them find the right solution and avoid common pitfalls. PalDock has been a great help, covering both current and future needs, and preventing the need for migrations to a more robust solution later on. Jan StejskalPartnerLeadmarket Monetizing display or link traffic has its limitations and doesn’t provide enough differentiation. We shifted our focus to delivering more value to our users and gaining a competitive edge. That’s when we started collecting leads and selling them through API to the highest successful bidder. PalDock handled all the technical heavy lifting, allowing us to concentrate on growing the business without getting bogged down by technical challenges. Martin MazurekCEOConverting Ads PalDock has made managing leads and partnerships so much easier. We used to juggle different tools for tracking and lead generation, which made things messy. Now, everything’s in one place. We can collect, track, and manage leads and clicks all from the same software. It’s saved us a ton of time and let us focus on growing the business. Jiří SillikCEOPatron finance Frequently AskedQuestions Why is Affiliate Marketing a Smart Business Strategy? The primary benefit of affiliate marketing is its effectiveness and cost efficiency. Partners earn commissions from their websites, followers, and other assets, while merchants gain valuable access to their user attention. Since merchants only pay for actual sales generated by affiliates, this model minimizes financial risk. Recommendations from trusted sources greatly enhance conversion rates, making affiliate marketing a powerful sales driver. How to choose the right affiliate management software? When selecting affiliate management software, start by analyzing the features you need right now and those you may require in the future. Avoid choosing a tool based solely on its price, as it may not meet your long-term goals and could face a costly migration later. Taking the time to evaluate your current and future needs will help you find a solution that effectively supports your growth and vision. Which affiliate marketing tools are important? Key affiliate marketing tools include robust and precise combination of cookie-based and cookie-less tracking for links, forms, and APIs, enabling effective performance monitoring through statistics. Providing affiliates with up-to-date promotional materials, accurate product feeds, and flexible commission structures with motivational bonuses (or penalties) helps drive sales. For service providers, lead generation features can be key to staying ahead of competitors and enabling affiliates to increase their volumes. What is affiliate marketing software? Affiliate marketing software is designed to track and report actions that trigger commissions, such as sales, leads, or clicks from affiliate links, forms, or APIs. In addition to these core functionalities, it provides other features like detailed reporting, automated commission calculations, and customizable promotional materials. Together, these capabilities form a comprehensive affiliate marketing platform that empowers both merchants and affiliate marketers to effectively sell products. When to Use Dedicated Software vs. Existing Affiliate Network? Dedicated software is ideal if you require customization, advanced features, full control, cost efficiency for high-volume traffic, data ownership, scalability for future growth, and independence from network restrictions. In contrast, existing affiliate networks offer a quick setup, access to a built-in pool of affiliates, lower upfront costs (though expenses will quickly rise as your program grows), and support resources. #### Compare URL: https://paldock.com/compare/ #### Consultancy Get More Conversions from Affiliate & Leadgen We help you launch, optimize, and scale affiliate and lead generation programs for better performance, stronger partner relationships, and more revenue. Contact Us Intro Get More Conversions from Affiliate & Leadgen. The right tool is only part of the equation. We help you turn strategy, setup, and execution into real results. Here’s what you get A complete mix of strategy, technology, and operations. Everything you need to grow your affiliate and leadgen channels efficiently. Tracking tool Selection & Implementation Precise Tracking Implementation Affiliate ProgramSetup & Management Affiliate Partner Acquisition & Activation Conversion Validations and Billing Automation Performance Optimization & Insights Technical and API Integrations Support Lead Gen Business Consulting Track Kickstart Your Affiliate Program We help brands launch and scale affiliate and lead generation channels that go beyond the standard affiliate setup. From choosing the right software and implementing accurate tracking to defining lead flows, partner models, payouts, and reporting, we help you build the full setup that serious partners expect. Whether you work with affiliates, brokers, comparison sites, lead generators, or a mix of partner types, we make sure your channel is measurable, reliable, and ready to scale. Manage Active Affiliate Management We manage your affiliate program on an ongoing basis so it stays active, competitive, and built for growth. We help with partner communication, recruitment, activation, incentives, campaign support, and regular performance optimization. Instead of leaving the program on autopilot, we actively work on the things that keep partners engaged and the channel moving forward. Track Lead Gen Experts at Your Disposal We help you build lead generation flows that do more than just collect contacts. From forms and validations to lead processing, routing, and post form logic, we design setups that improve conversion rate, lead quality, and operational control. We make sure your leadgen flow works as a real system, not just a form connected to a spreadsheet. Let’s talk Tell us what problem you’re trying to solve, and we’ll come up with the right solution. Contact Us Trusted by marketers. Designed for results. Ready to outperform the competition? Request a demo Start for free #### Contact us Based on real Affiliate Marketing Experience The name PalDock comes from our goal of helping partners (pals) dock with advertisers and creating a reliable harbor for cooperation. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Company details PalDock.com is company registered in Europe. Our registered address is Pricna 1892/4, Prague, Czech Republic, and our VAT ID is CZ04458206. If you have any questions or concerns about our legal status or operations, please don’t hesitate to contact us on info at paldock.com. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → #### Cookie Declaration Cookie Declaration We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Cookie Declaration We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you’ve provided to them or that they’ve collected from your use of their services. Cookies are small text files that can be used by websites to make a user’s experience more efficient. The law states that we can store cookies on your device if they are strictly necessary for the operation of this site. For all other types of cookies we need your permission. This site uses different types of cookies. Some cookies are placed by third party services that appear on our pages. You can at any time change or withdraw your consent from the Cookie Declaration on our website. Learn more about who we are, how you can contact us and how we process personal data in our Privacy Policy. Your consent applies to the following domains: app.paldock.com, paldock.com One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → #### Data Security Data Security The commitment to security is a top priority for us, so we are continuously striving to improve and adapt measures to counter evolving threats. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro We have a number of technical and organizational measures in place at several levels to safeguard the confidentiality, integrity and availability of all data and ensure the overall security of our services. Encryption and Data Security Our systems are encrypted using industry-standard cryptographic protocols such as TLS (Transport Layer Security). Data at rest is encrypted using strong encryption algorithms, adding an extra layer of protection to stored information. Regular data backups are performed to ensure data integrity and availability.  Access Management Access to our systems and databases is strictly controlled based on the principle of least privilege. User access is granted only to authorized personnel after proper identification, the access is granted based on the “need-to know” principle. We do employ robust authentication mechanisms, such as multi-factor authentication (MFA), to ensure secure user access. Accesses to our system are monitored and regularly audited during security audits.  Cloud Security We host our infrastructure with Hetzner Online GmbH. Hetzner operates ISO/IEC 27001:2022 certified data centre operations and provides documented technical and organisational measures, including physical security controls, access control, and monitoring. A Data Processing Agreement is available to support GDPR requirements for processor relationships. ISO 27001 certification overview: https://www.hetzner.com/unternehmen/zertifizierung/ ISO certificate (PDF): https://www.hetzner.com/assets/downloads/ISO-Certificate.pdf Hetzner Data Processing Agreement DPA (PDF): https://www.hetzner.com/AV/DPA_en.pdf Hetzner Technical and Organisational Measures, Appendix 2 TOMs (PDF): https://www.hetzner.com/AV/TOM_en.pdf Technical and organisational measures overview (includes physical security examples): https://docs.hetzner.com/general/others/technical-and-organizational-measures GDPR Compliance We are compliant with the Regulation (EU) 2016/679 of the European Parliament and of the Council on the protection of natural persons with regard to the processing of personal data and on the free movement of such data (GDPR). For more information about personal data protection please see our Privacy policy. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → #### E-commerce Affiliate Software Affiliate software for e-commerce Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Key Features to Look for in Software for online stores The right tool should let you track all traffic and conversions accurately, manage affiliate partners efficiently, keep marketing assets always up to date and simplify invoicing. With PalDock you get all of this in one platform, built to maximize performance and scale your business. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free Track Cookie-less Tracking Tracking might sound basic, but in e-commerce it can get complex. Cookie tracking fails when orders are not approved instantly or when the product is processed through a call center. Clients often need verification or a follow-up, which makes cookie-based tracking unreliable. That is why PalDock combines cookie and cookieless tracking to deliver the highest level of accuracy. Every conversion is counted, even when the process takes longer. Optimize Commission adjustments It is smart to set penalties for cancellations so affiliates are rewarded only for real, lasting sales. Penalties can be a fixed fee, the full commission originally paid, or an amount adjusted based on how long the customer stayed before canceling. This way, you protect your revenue while keeping the commission model fair for everyone. Aggregate Aggregate Product Data Affiliate marketing in e-commerce is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds. The best part? Updates sync automatically with XML changes, but you also have the flexibility to tweak things manually.  Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Generate Generate banner from feeds Easily create banners from your Product Data Feed. Whether you need banners for specific products, categories, or any other criteria, our system ensures they’re always updated with the latest product information or highlights the top product in its category. Say goodbye to manual updates; enjoy seamless and automatic banner generation. Build Always-Up-To-Date Assets Take full control over your marketing assets with easy management of expiration dates and post-expiration content. Say goodbye to outdated banners or information on affiliate sites. Affiliates can enjoy the benefits of auto-updating HTML banners or tap into real-time product feeds. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Evaluate Reporting The best part is that PalDock lets you track both clicks and lead performance seamlessly in one place. No more juggling two tools or wasting time on custom setups. All parties get access to a real time dashboard where they can see and verify data, which brings full transparency and eliminates the need for sending Excel files back and forth. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features #### Everflow Alternative What is Everflow? Everflow positions itself as an all-in-one performance marketing platform, but at its core it’s still a classic affiliate tracker. Most of its value lies in link tracking and postback management, while many of the “extra” features, like partner tools or media buying modules, feel more like bolt-ons than integrated solutions. The result is a bloated product that tries to cover everything, but rarely excels in the areas beyond tracking. For teams that just want to manage affiliate traffic efficiently, Everflow often feels heavier, overpriced and more complex than it needs to be. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Everflow vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: EverflowPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### FirstPromoter Alternative What is FirstPromoter? FirstPromoter is a simple affiliate tool designed mainly for SaaS companies that need basic referral tracking. It covers the essentials such as links, payouts and simple partner dashboards but not much beyond that. The platform is easy to set up yet lacks flexibility, automation and deeper analytics that modern programs require. It also offers very limited customization and poor scalability once you move beyond a small group of partners. For startups it can be a quick fix but for any serious affiliate operation it becomes restrictive very fast. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → FirstPromoter vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: FirstPromoterPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### FunnelFlux Pro Alternative What is FunnelFlux Pro? FunnelFlux Pro is marketed as a visual funnel tracker, but in practice it is mostly a rebranded link tracker with a flowchart UI on top. The visual editor looks appealing at first yet quickly becomes messy and hard to maintain for larger setups. Despite the promise of “unlimited flexibility” most users end up using it for simple affiliate flows, because anything more complex turns into chaos. Reporting and integrations lag behind modern standards, and the overall user experience feels clunky compared to newer API-driven solutions. FunnelFlux Pro might work for solo media buyers, but for structured affiliate programs or networks it is more of a limitation than a help. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → FunnelFlux Pro vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: FunnelFlux ProPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### General Terms of Service General Terms of Service This page outlines the general terms and conditions that govern the use of our services. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro Leadgen Labs s.r.o., a company registered in the commercial register maintained by the Municipal Court in Prague, Section C 247987, identification number 04458206, with its registered office at Příčná 1892/4, 110 00 Praha, Czech Republic (hereinafter referred to as the “Provider”), provides its customers (hereinafter referred to as the “Tenant” or the “Tenants”) a web-based application used to manage and track activities in the area of affiliate marketing (hereinafter referred to as the “Application”), including campaign setup, cooperation between advertisers, affiliates and networks, and related tracking, attribution, reporting, and lead capture and distribution (as applicable). Users of the Application may include the Tenant’s internal users as well as authorised users of third parties collaborating with the Tenant in affiliate marketing, such as advertisers, affiliates and networks (collectively, “Users”). A Tenant may act as an advertiser, an affiliate, or an affiliate network. By accessing and using the Application, the Tenant enters into a contractual relationship with the Provider (the “Agreement”) and acknowledges that the Tenant has read and understood these General Terms of Service (the “Terms”) and the Provider’s Privacy Policy and agrees to be bound by both. The Tenant also acknowledges and authorises that, for the purpose of providing the Application, the Provider will process personal data of Users invited by the Tenant to the Tenant’s space in the Application collectively, “User Data” as further described in the Data Protection and Roles section below. Definitions “Users” means any natural person authorised by the Tenant to access the Tenant’s space in the Application, including the Tenant’s internal users and authorised users of third parties collaborating with the Tenant (such as advertisers, affiliates and networks). “User Account Data” means personal data processed by the Provider as an independent controller to create and administer User accounts and access to the Application and to operate and secure the Application, including authentication data, access credentials, access logs, security logs, service logs, billing identifiers, and communications related to account administration and support. “User Data” means personal data relating to Users processed within the Tenant space in connection with access and use of the Application for Tenant purposes, such as User identity, role, permissions, and activity within the Tenant space, to the extent this constitutes personal data under applicable law. “Lead Data” means personal data of end customers or prospects submitted to, collected in, or processed through the Application on behalf of the Tenant, including data received via forms, APIs, imports, webhooks, postbacks, or similar integrations, for the purpose of lead capture, lead distribution, attribution, reporting, or related Tenant marketing activities. “Tracking Data” means technical identifiers and event data generated through the use of the Application for tracking and attribution, such as click identifiers, event identifiers, timestamps, URLs, user agent strings, device or browser information, and IP addresses, to the extent such data constitutes personal data under applicable law. “Tenant Data” means all data the Tenant inputs into or processes through the Application, including User Data, Lead Data, and Tracking Data “Provider Diagnostic Data” means service logs, telemetry, security and billing identifiers that the Provider needs to operate, secure and improve the Application. Tenant’s declarations By accessing and using the Application the Tenant declares that: he is a business entity with full legal capacity without any limitations. The Application is intended for a commercial use only. All users accessing the Application on behalf of a Tenant must be over 18 years old. he is aware that he is solely and fully responsible for its marketing materials, promotions, placements, creatives, landing pages and overall compliance with the laws in all jurisdictions where such activities are carried out. he provides the Provider with true and accurate data at all times. In case of any changes in Tenant’s data during the relationship with the Provider, the Tenant shall notify the Provider about that without any undue delay. If the data provided are not true and accurate, the Provider reserves a right to block or even cancel the access to the Application with immediate effect.  he is aware that he shall be charged by the Provider for the use of Application according to the range of service used  he is aware that he is solely and fully responsible for his relationships and obligations towards other Users and third parties collaborating with the Tenant (including advertisers, affiliates and networks), including the content and compliance of any marketing activities, placements, creatives, landing pages, and disclosures required by applicable law. he is aware that he is solely and fully responsible for the security of his username(s) and password(s). The Provider shall not be held liable for any damage arising from Tenant’s security failure, he agrees and understands that the Provider uses hosting partners and other third party vendors to provide the necessary software and hardware to run the Application.  he acknowledges the Provider’s processing of User Data as described in the Data Protection and Roles section, including the Provider’s independent-controller processing to operate and secure the Application. he authorises the Provider to present and capture both the Tenant and Provider acceptance in the user onboarding flow and to retain proof of acceptance. Data Protection and Roles Tenant as controller for Tenant DataThe Tenant determines the purposes and means of processing of Tenant Data, including Lead Data, Tracking Data, and User Data within the Tenant space, in connection with the Tenant campaigns, lead capture, lead distribution, attribution, and reporting. For these purposes, the Tenant acts as the controller and is responsible for ensuring a valid legal basis, transparency notices, and any required consents towards end customers, prospects, Users, and other data subjects. Provider as processor for Tenant Data, including Lead DataFor the purpose of providing the Application to the Tenant, the Provider processes Tenant Data strictly on documented instructions from the Tenant and acts as a processor for such processing. The Provider will not process Tenant Data for its own purposes. The Provider may process Tenant Data only as necessary to provide, maintain, and support the Application, including troubleshooting, customer support, and implementing security measures, always in a manner consistent with the Tenant instructions and these Terms. Provider as independent controller for User Account Data and Provider Diagnostic DataThe Provider processes User Account Data and Provider Diagnostic Data as an independent controller for purposes necessary to operate, secure, maintain, and improve the Application, including account and access management, authentication, security monitoring, fraud prevention, service logs, diagnostics, billing, and service analytics. The Provider Privacy Policy applies to this processing. Lead Data anonymisationWhere available, the Application may provide functionality allowing the Tenant to anonymise Lead Data in the Application. The Tenant may configure anonymisation to occur immediately upon receipt of Lead Data or after a configurable retention period following receipt. After anonymisation, the data is no longer intended to identify a natural person. The Tenant acknowledges that anonymisation may limit certain features, reporting, attribution, or support capabilities, depending on configuration. The Provider will not attempt to reverse anonymisation or re-identify anonymised data. Data residency and processing locationsWhere offered for the selected plan or agreed in an order form, the Tenant may select a primary data region for storage and processing of Tenant Data, typically within the European Union or the United States. The Provider will use reasonable efforts to process and store Tenant Data in the selected region. The Tenant acknowledges that limited cross region access may occur where necessary for support, security, and reliability, including by authorised personnel and subprocessors, subject to appropriate safeguards and confidentiality obligations. Any additional regions, if offered, will be described on the Provider website or agreed in an order form. Data Processing Addendum This Data Processing Addendum forms part of the Agreement and applies to the processing of personal data included in Tenant Data. Scope and rolesFor Tenant Data, including Lead Data and Tracking Data, the Tenant acts as controller and the Provider acts as processor. Provider Diagnostic Data and User Account Data are processed by the Provider as independent controller as described in these Terms. Documented instructionsThe Provider will process Tenant Data only on documented instructions from the Tenant. The Tenant instructions include, in particular, the Tenant configuration and use of the Application features and any written instructions provided through support channels. The Provider may process Tenant Data to comply with applicable law. Confidentiality of personnelThe Provider ensures that persons authorised to process Tenant Data are bound by confidentiality obligations. Security measuresThe Provider will implement appropriate technical and organisational measures designed to protect Tenant Data against accidental or unlawful destruction, loss, alteration, unauthorised disclosure, or access. High level information about measures may be provided on request. The Tenant acknowledges that security measures may evolve over time. SubprocessorsThe Tenant authorises the Provider to use subprocessors to process Tenant Data for the purpose of providing the Application. The Provider will impose data protection obligations on subprocessors consistent with this Addendum and remains responsible for their performance. A current list of subprocessors may be published on the Provider website or made available on request. The Provider will use reasonable efforts to notify the Tenant of material changes to subprocessors where practicable. International transfersWhere processing of Tenant Data involves transfers outside the EEA, the Provider will ensure appropriate safeguards are in place, such as standard contractual clauses, where required. Assistance and data subject requestsThe Provider will provide reasonable assistance to the Tenant to respond to data subject requests, taking into account the nature of processing and the information available to the Provider. The Provider may charge reasonable fees for excessive or manifestly unfounded requests. Personal data breachThe Provider will notify the Tenant without undue delay after becoming aware of a personal data breach affecting Tenant Data and will provide information reasonably necessary to support the Tenant compliance obligations. Deletion and returnUpon termination of the Agreement, the Provider will, at the Tenant choice, delete or return Tenant Data within a reasonable time, unless retention is required by law or for legitimate security and compliance purposes. The Tenant is responsible for exporting Tenant Data prior to termination. AuditUpon written request and no more than once per year, the Provider will make available reasonable information necessary to demonstrate compliance with this Addendum, such as third party audit summaries or security documentation, where available, subject to confidentiality and security restrictions. User onboarding and acceptance The Tenant may invite Users, including Affiliates and their authorised users, to access the Tenant space in the Application. Each such User is provided with an account in the Application and, as part of onboarding, accepts these Terms and acknowledges the Provider Privacy Policy for purposes of account and access management, authentication, security monitoring, fraud prevention, service logs, diagnostics, billing, and service analytics. The Provider stores evidence of such acceptance. The Tenant is responsible for managing invited Users access and permissions within its Tenant space and for ensuring that invited Users use the Application only for the Tenant legitimate business purposes. The Tenant remains responsible for its relationship with invited Users and for any Tenant specific processing of personal data within the Tenant space. Where the Tenant requires its own terms, notices, or consents from invited Users for Tenant purposes, the Tenant may present them within the Tenant onboarding flow and the Provider may record evidence on the Tenant behalf on documented instructions from the Tenant. The Provider may, at its sole discretion and without liability, suspend or terminate access for any invited User if the Provider reasonably believes that the User engages in conduct that would constitute a breach of these Terms if performed by the Tenant, or compromises or attempts to compromise the security, stability, or proper functioning of the Application. Privacy requests related to Tenant processing are handled by the Tenant. Privacy requests related to Provider processing are handled by the Provider. The Application (provided services) and acceptable use Packages and scope of servicesIn the Application, the Provider offers different packages with different ranges of services, tools and functionalities. These services, tools and functionalities are designed to facilitate and improve the Tenant’s marketing activities via third parties in the area of affiliate marketing. The detailed content of individual packages is specified on the Provider’s website, as well as the respective subscription fees and other individual conditions. Custom DevelopmentThe Provider may, upon the Tenant’s written request, develop custom features or functionalities tailored to the Tenant’s specific needs. Custom development is subject to a separate written agreement specifying the scope, timeline, and fee. Custom development fees are determined on a case-by-case basis. As a general guideline, a fee of EUR 200 per hour applies per custom feature developed exclusively for the Tenant. Where the Provider determines, at its sole discretion, that the requested feature is suitable for general availability within the Application and will be made available to other tenants, a reduced fee of EUR 100 per hour may apply. Free version and limitsThe Application may be available under a base free plan with defined usage limits published on the Provider website or in the Application. If the Tenant reaches the applicable free plan limit, the Provider will notify the Tenant in the Application and, where available, by email. If the Tenant exceeds the free plan limit, the Provider will grant a grace period of seven calendar days to allow the Tenant to upgrade to a paid package or to reduce usage back within the free plan limits. During the grace period the Provider may apply reasonable technical measures to prevent further excess usage, for example by limiting new tracking events, requests or API calls, while keeping the Tenant access to the Application and data available for review and upgrade. If the Tenant does not upgrade and does not return within the free plan limits by the end of the grace period, the Provider may suspend the Tenant access to the Application until the Tenant upgrades or usage returns within the free plan limits. Paid packages, limits and overage feesThe Application’s paid packages may also have limits on the range of services, tools and functionalities provided in the respective package. These limits are specified in detail on https://paldock.com/pricing/. When automatic upgrade is enabled (default). Automatic upgrade is enabled by default and can be managed in the Application settings. If the Tenant exceeds any limits of its current package during a billing period, the Provider may immediately upgrade the Tenant to the next package tier for the remainder of that billing period and charge the price difference between the original and higher package (pro-rated for the remaining days), as set out on https://paldock.com/pricing/. From the next billing period, the Tenant is charged the full subscription fee for the higher package unless the Tenant requests a downgrade, which will take effect from the following billing period. When automatic upgrade is disabled. If the Tenant disables automatic upgrade in the Application settings and then exceeds the maximum payout volume of its current package during a billing period, the Tenant remains on that package and the excess payout amount is billed as an overage fee at the end of the billing period, in addition to the regular subscription fee. The overage fee is calculated at the average fee rate (as in pricing) applicable to the Tenant’s current package tier plus a surcharge of 1 percentage point. For the avoidance of doubt, by accepting a paid package the Tenant authorises the Provider to charge the Tenant’s chosen payment method for the relevant subscription fees and any additional amounts arising under these Terms, including automatic upgrades and usage beyond package limits. Excessive load and fair useThe Application is provided on a fair use basis. If the Tenant usage creates an excessive technical load that materially affects the stability, security or performance of the Application, or causes disproportionate costs to the Provider, the Provider may apply proportionate technical measures to protect the service. The Provider will use reasonable efforts to notify the Tenant in advance and provide a cure period of seven calendar days to remedy the situation, for example by reducing usage, upgrading to a higher package, or agreeing on custom terms.During the cure period the Provider may temporarily throttle or limit specific high load functions while keeping the Tenant access to the Application and data reasonably available. If the Tenant does not remedy the excessive load within the cure period, the Provider may suspend access until the issue is remedied. Immediate action without prior notice may be taken only where necessary to protect the Application or other customers, for example in cases of security incidents, suspected abuse, fraud, or unlawful activity. In such cases the Provider will notify the Tenant as soon as reasonably practicable. Accurate transaction reportingThe Tenant is obliged to ensure that all valid transactions, conversions and other billable generated events are properly reported and recorded in the Application. This obligation applies regardless of whether tracking is implemented via technical integration (postback, API, pixel or similar) or by manual upload. Deliberately failing to implement tracking, disabling or bypassing tracking, or intentionally withholding transactions from the Application will be treated as artificial revenue manipulation and a material breach of these Terms. Reporting currency and FX conversionsThe Application may allow Users to select a preferred display currency for reporting and dashboard purposes. Any currency conversions shown in the Application are provided for convenience only and are indicative. They are calculated using exchange rates determined by the Provider or obtained from third party sources at a given time and may include rounding. For the avoidance of doubt, commissions, payouts, and any invoicing between the Tenant and other Users or third parties are governed by the original currency of the relevant offer, program, or transaction as recorded in the Application (the “Offer Currency”). The display currency does not change the underlying transaction currency and does not constitute an accounting, tax, or invoicing record. Artificial revenue manipulationAny form of artificial revenue manipulation is strictly prohibited within the Application. This includes, in particular, intentionally reducing authentic Affiliate-generated revenue figures. Engaging in such activities will result in immediate account termination, in accordance with the Termination section of the Terms. The Provider is fully committed to upholding the integrity of the Application and ensuring its fair and honest use by all its users. Intellectual property rightsAll rights, above all but not limited to intellectual property rights, to the Application are licensed to or owned by the Provider. The Application shall not be reproduced, distributed or copied without prior written authorisation by the Provider. Prohibited usesThe Tenant shall not use or promote (or instruct others to use) the Application for any fraudulent, illegal or otherwise harmful purpose, above all but not limited to any criminal behavior, terrorism, pornographic or defamatory material. The Tenant shall not use any software or other technical device to attempt to interfere with the proper functioning of the Application. Price  The price for the services provided in the Application is billed as a monthly or yearly subscription fee based on the package chosen by the Tenant. Subscription fees are charged in advance for each billing period. The subscription fees and applicable limits are listed in the Provider’s price list published on https://paldock.com/pricing/ (the “Standard Price”), unless the parties agree on different pricing in a written Order Form (the “Individual Pricing”). Individual Pricing is valid for the period specified in the respective Order Form. If no period is specified, Individual Pricing expires 12 months from its effective date. Upon expiration, the Tenant’s account will automatically transition to the Standard Price effective from the next billing period. Overage fees are charged at the end of the billing period in which they accrue, unless agreed otherwise. If the Tenant package is upgraded during a billing period in accordance with these Terms, the Provider may charge the applicable price difference for that period immediately upon the upgrade. By selecting a paid package, the Tenant authorises the Provider to charge the Tenant chosen payment method on a recurring basis for subscription fees, any applicable overage fees, and other amounts due under these Terms. If the parties agree in writing on an alternative payment method, the Provider may invoice the Tenant electronically, with payment due within fourteen calendar days from the invoice date unless a different due date is agreed in an order form. The Provider may, upon the Tenant’s request, consolidate multiple invoices issued within a billing period into a single consolidated invoice. A consolidation fee of 3% of the total consolidated amount applies, with a minimum fee of EUR 50 per consolidation request. Where invoices are denominated in multiple currencies, a separate consolidated invoice is issued for each currency. The Provider may update the Standard Price or notify the Tenant of the expiration of Individual Pricing with at least 30 calendar days’ notice. If the Tenant does not agree with the change, the Tenant may terminate the Agreement before the change takes effect. Continued use of the Application after the effective date constitutes acceptance of the new price. If a payment fails or is reversed, the Provider may retry the charge and may suspend access to the Application after providing notice in the Application and, where available, by email. Access will be restored after all outstanding amounts are paid. Except where required by applicable law or expressly agreed in a separate insertion order or order form, fees are non refundable and the Provider does not provide refunds or credits for partial billing periods, unused capacity, downgrades, or unused services. All subscription fees, overage fees, package descriptions, and applicable limits are listed in the Provider price list published on https://paldock.com/pricing/. All fees are exclusive of taxes and duties imposed by applicable authorities. The Tenant is solely responsible for its tax payments and tax reporting obligations. Confidentiality Confidential InformationConfidential Information means any non public information disclosed by one party to the other in connection with the Agreement, whether in written, oral, visual, electronic, or other form, including business, technical, financial, commercial, product, and security information, the Application, documentation, pricing for the Tenant, and Tenant Data. Confidential Information does not include information that the receiving party can demonstrate is publicly available without breach, was lawfully known before disclosure, is independently developed without use of Confidential Information, or is lawfully received from a third party without restriction. Confidentiality obligationsThe receiving party will use Confidential Information only as necessary to perform its obligations and exercise its rights under the Agreement, will protect it with at least reasonable care, and will not disclose it to any third party except to its employees, contractors, and subprocessors who have a need to know and are bound by confidentiality obligations at least as protective as these Terms. Compelled disclosureIf the receiving party is required by law or by an authority to disclose Confidential Information, it will, to the extent legally permitted, notify the disclosing party in advance and cooperate to seek protective measures. The receiving party will disclose only the minimum required. Return or deletionUpon termination of the Agreement and upon request, the receiving party will return or delete the other party Confidential Information, except where retention is required by law or for legitimate compliance, security, or audit purposes. DurationThese confidentiality obligations apply during the Agreement and for three years after termination. Trade secrets remain protected as long as they remain trade secrets. Liability Disclaimer and availabilityThe Application and any related services are provided as is and as available, unless expressly agreed otherwise in a separate insertion order or order form. The Provider will use reasonable efforts to maintain the accessibility and functionality of the Application. The Tenant acknowledges that access to the Application may be temporarily limited due to maintenance, repairs, updates or circumstances beyond the Provider’s reasonable control. For the avoidance of doubt, the Tenant has no right to a discount and no right to terminate the Agreement with immediate effect solely due to temporary unavailability of the Application or any part of it. Exclusion of certain types of damagesTo the maximum extent permitted by law, in no event shall the Provider be liable for any indirect, incidental, special, exemplary, punitive or consequential damages, or for any loss of profit, loss of revenue, loss of business, loss of goodwill, loss of data, business interruption or procurement of substitute services, arising out of or relating to the Agreement, these Terms or the access to, use of, or inability to use the Application, regardless of the legal basis of the claim and even if the Provider has been advised of the possibility of such damages. Financial limitation of liabilityTo the maximum extent permitted by law, the Provider total aggregate liability for any and all claims arising out of or relating to the Agreement, these Terms, or the Application shall not exceed the total amount of subscription fees actually paid by the Tenant to the Provider for the Application during the three months immediately preceding the event giving rise to the claim, unless a different cap is expressly agreed in a separate insertion order or order form. Exceptions and clarificationsNothing in these Terms limits or excludes liability that cannot be limited or excluded under applicable law. The exclusions and limitations in this Liability section shall not apply to liability for death or personal injury caused by the Provider’s negligence, or to fraud or wilful misconduct, to the extent such liability cannot be excluded. The Provider is not responsible for the content, form or legality of the Tenant’s advertisements, the Tenant’s compliance with laws in any jurisdiction, or for any acts or omissions of the Tenant’s Affiliates or other third parties engaged by the Tenant. The Provider shall not be liable for any damage arising from the Tenant’s failure to pay any Affiliate or other third party in full and on time. To the maximum extent permitted by law, the Provider is not liable for any loss or damage caused by viruses or other technologically harmful material that may infect the Tenant’s equipment or data due to the Tenant’s access to the Application or the Provider’s websites. The limitations and exclusions in this Liability section do not limit the Tenant’s obligation to pay all fees and other amounts due under the Agreement, including subscription fees, overage fees and any applicable taxes. Tenant indemnityIf the Provider is addressed by any third party, including any authority, with an assertion that any conduct of the Tenant or any User via the Application is contrary to law, infringes rights, or otherwise gives rise to a claim, the Tenant undertakes to defend the Provider and hold the Provider harmless, solely at the Tenant’s expense, from and against any damages, losses, liabilities, costs and expenses, including reasonable legal fees, arising from such claim. In such a case the Provider is entitled to suspend access to the Application until the situation is corrected or explained to the Provider’s satisfaction. The Tenant has no right to any reimbursement or discount for the period of suspension. Termination  The Tenant is entitled to terminate the Agreement without a reason. Termination notice shall be given to the Provider via the Application or sent by the email to support@paldock.com. Termination notice shall be considered as delivered immediately when given via the Application or the third working day when sent by the email. The Agreement will be terminated by the end of the last paid subscription period.   The Provider is entitled to terminate the Agreement with immediate effect in case of a Tenant’s breach of these Terms, primarily, but not only, in case of using the Application for any illegal purposes. In such a case the Tenant is not entitled to demand a refund of any part of the subscription fee paid. The Tenant shall not violate any laws of the respective jurisdiction in which he advertises his services or products with any help of the Application.  Final provisions Governing lawThese Terms, the Agreement, and all mutual relations and obligations arising from them are governed by Czech law, in particular Act No. 89/2012 Coll., the Civil Code, as amended. Changes to these TermsThe Provider may amend these Terms from time to time. The Provider will notify the Tenant about material amendments in the Application and, where available, by email. Unless a longer period is required by applicable law, amendments become effective fourteen calendar days after the notice is given. If the Tenant does not agree with the amendment, the Tenant may terminate the Agreement by giving notice to the Provider before the effective date of the amendment. Continued use of the Application after the effective date constitutes acceptance of the amended Terms. Supplemental termsThe Provider may provide specialized supplemental terms of service for additional services or features. If such supplemental terms conflict with these Terms, the supplemental terms prevail for the relevant service or feature, unless explicitly stated otherwise. NoticesNotices under these Terms must be provided in writing. The Provider may provide notices to the Tenant by email to the Tenant administrator email address, by in Application notification, or by posting an update within the Application. Notices to the Provider must be sent to support@paldock.com unless a different address is specified in an insertion order or order form. Email notices are deemed received on the next business day. AssignmentThe Tenant may not assign the Agreement without the Provider prior written consent. The Provider may assign the Agreement to an affiliate, or in connection with a merger, acquisition, reorganisation, or sale of all or substantially all of its assets, by providing notice to the Tenant. Force majeureNeither party is liable for any failure or delay in performance to the extent caused by events beyond its reasonable control, including natural disasters, war, terrorism, civil unrest, strikes, epidemics, power outages, internet or telecommunications failures, third party service failures, governmental actions, or denial of service attacks, provided that the affected party uses reasonable efforts to mitigate the impact and resumes performance as soon as reasonably practicable. If a force majeure event continues for more than thirty calendar days, either party may terminate the Agreement by written notice. SeverabilityIf any provision of these Terms is held invalid or unenforceable, the remaining provisions remain in full force and effect. No waiverFailure to enforce any provision of these Terms is not a waiver of future enforcement of that provision or any other provision. Relationship of the partiesThe parties are independent contractors. Nothing in these Terms creates a partnership, agency, fiduciary relationship, or employment relationship between the parties. SurvivalSections relating to intellectual property, confidentiality, liability, payment obligations, dispute resolution, and any provisions that by their nature should survive, survive termination of the Agreement. Limitation periodTo the maximum extent permitted by law, any claim arising out of or relating to the Agreement or these Terms must be brought within one year of the event giving rise to the claim. JurisdictionThe Provider and the Tenant agree that any dispute arising from use of the Application or in relation thereto shall be decided exclusively by the District Court Prague 1 if district courts have jurisdiction in the first instance, or by the Municipal Court in Prague if regional courts have jurisdiction in the first instance. Language versionsThese Terms may be available in different language versions. In case of any discrepancy between the English language version and any other version, the English language version prevails. #### Get started Start Today, Grow Tomorrow! Book a quick call and share a bit about your goals. We will come prepared, walk you through the best approach, and set you up with trial access. #### iGaming Affiliate Software Affiliate software for iGaming Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Key Features to Look for in Software for iGaming The right platform should give you everything from easy affiliate partner recruitment and management, customizable commission structures with flexible formulas, to precise affiliate link tracking. To take your program further, you also need advanced features such as cookie-less conversion tracking, automated service and product feeds that keep affiliate sites updated with current events and offers. With PalDock you get all of this in one platform, designed to maximize performance and drive higher revenues in the betting industry. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free Track Cookie-less Tracking Tracking might sound basic, but in iGaming it quickly gets complicated. Cookie tracking breaks down when deposits are not approved instantly or when players need extra verification and follow-up. This makes cookie-based tracking unreliable and costly. That is why PalDock combines cookie and cookieless tracking to deliver maximum accuracy. Every conversion is captured, even when the player journey takes longer. Optimize Custom commission structures Tailor your commission structures to fit any model you need, whether it is CPA, revenue sharing or a custom formula, and align them with diverse conversion goals from different revenue streams. You can even combine CPA with revenue share or set conditions for commission payments based on specific criteria such as the first-time deposit amount. For example, a casino might offer a USD 50 commission for a player who deposits USD 30, while a smaller deposit would not activate the CPA payment. To further motivate affiliates, you can also add one-time or automated bonuses and apply penalties when necessary, giving you full flexibility to optimize performance. Aggregate Commission adjustments It is smart to set penalties for cancellations so affiliates are rewarded only for real, lasting sales. Penalties can be a fixed fee, the full commission originally paid, or an amount adjusted based on how long the customer stayed before canceling. This way, you protect your revenue while keeping the commission model fair for everyone. Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Generate Commission formula You can design your own commission formula and include exactly the elements that matter to your business, from marketing and branding expenses to attribution costs, bonuses, gaming operations, banking fees or even the point of consumption tax. For example, in gambling you might calculate commissions from gross gaming revenue after deducting taxes, platform fees, bonuses and other expenses, ensuring affiliates are paid fairly from real net value. Each bet is automatically tracked, so commissions rise with player losses and decrease with wins, with the option to enable negative carryover if you want to transfer losses between months. You can also set how long commissions are paid based on customer activity – one year, two years or even lifetime value. Build Always-Up-To-Date Assets Take full control over your marketing assets with easy management of expiration dates and post-expiration content. Say goodbye to outdated banners or information on affiliate sites. Affiliates can enjoy the benefits of auto-updating HTML banners or tap into real-time product feeds. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Evaluate Reporting The best part is that PalDock lets you track both clicks and lead performance seamlessly in one place. No more juggling two tools or wasting time on custom setups. All parties get access to a real time dashboard where they can see and verify data, which brings full transparency and eliminates the need for sending Excel files back and forth. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features #### Impact Alternative What is Impact ? Impact is one of the biggest names in partnership automation, but its size comes with complexity. The platform offers a vast ecosystem of features for tracking, contracting and managing partners, yet the interface often feels slow and unintuitive. Many users find setup and campaign management cumbersome, with basic actions buried under layers of configuration. While Impact delivers strong reporting and integrations, it is better suited for enterprise teams with dedicated staff than for lean marketing operations. For smaller or mid-sized programs it often feels like using a corporate ERP to send an email. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Impact vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: Impact PalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Integration Integration You can find here integration-focused PalDock documentation in AI-ready Markdown format. Together, these resources help your AI assistant create and manage PalDock integrations: Integrations – integration rules, best practices, and examples. Integration Know-how – API documentation, PalDock blueprints, and practical know-how for dozens of integrations. We recommend using a dedicated project in your AI tool because the Knowledge Base and Integration documentation are extensive, while AI tools have limited context available within each project. All Advertiser Tracking Validation Sell leads to Hyperia (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Volsor (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Kamali (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Creditportal (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to 7finance (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Rerum (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Tando (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to PůjčkaPlus (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to CreditGO (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Zaplo (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to CreditKasa (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. Sell leads to Ferratum (CZ) Maximize revenue from your leads by connecting this advertiser to your PalDock workspace. The integration is prebuilt, so you can go live in a few clicks, no developer needed. 1 2 #### Kiflo Alternative What is Kiflo? Kiflo is an affiliate and partner management platform that tries to cover everything from referrals to reseller programs, but often ends up feeling generic. The interface is clean, yet the user experience is rigid and lacks the level of customization larger programs need. Reporting and integrations are basic, and the pricing can feel high compared to the actual feature depth. Kiflo may work for small SaaS teams that want a simple all-in-one partner tool, but it quickly hits limits once you need more granular control or advanced automation. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Kiflo vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: KifloPalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Knowledge base Knowledge base Here you can find documentation about using PalDock and its features. You can provide the PalDock documentation to your AI assistant in AI-ready Markdown format. The documentation is split into two files due to its size: Knowledge Base – explains how to use and configure the PalDock application. Integrations and Integration knowhow (mainly this article) – focused on dozens of integrations, including API documentation, PalDock blueprints, and our integration know-how. This allows your AI assistant to create and manage integrations. We recommend using a dedicated project in your AI tool because the Knowledge Base and Integration documentation are extensive, while AI tools have limited context available within each project. Generic selectors Exact matches only Search in title Search in content Post Type Selectors Getting startedStart hereBasic visual cuesOne Account, Multiple WorkspacesDashboardConversion -> Commission -> TransactionShow moreUser ManagementAbout User managementAffiliatesAdvertisersAdminsReports and LogsAbout Reports and LogsHighlightsShow rows in chartAdvanced columnsFiltersShow moreOffersAbout OffersAllowed Delivery methodAdvertiserOffer organizationCurrencyShow moreCommissionsAbout commissionsHow the commission is selectedCommission statusCommission conditions to create TransactionsMultiple Commissions for the Same Conversion TypeShow moreTrackingAbout TrackingConversion IDs explainedTracking processingConversion typeTracking pixelShow moreStructuresAbout structuresLocal, Global and Custom fieldsField settingsField typesField validationShow moreConnection CreatorAbout connection creatorWhere Connection Creator is usedCustom keysEditorHow to integrate anythingShow moreGeneral toolsCondition Operators and valuesGroup changesParametersSettingsAbout settings #### Media kit URL: https://paldock.com/media-kit/ #### PalDock Affiliate. Lead Generation. Monetization. All-in-one. From click to payout, manage affiliate links and offers, capture leads via forms and APIs, route each lead to the best buyer, integrate with anything, and measure everything. Try for Free → Want to talk or get a live demo? Get in touch → Ecosystem for Partners, Brokers, Advertisers and Networks Publisher Track conversions from centrally managed campaigns and links and optimize with reports. Learn more Broker Aggregate traffic from multiple sources and deliver it to advertisers through no-code API integration. Learn more Network Connect partners and advertisers through links or lead generation. Create your own products. Learn more Advertiser Invite, onboard, and manage affiliates. Set custom commissions and evaluate results in reports. Learn more AI powered tools. Seamlessly connected. Everything’s connected — links, forms, traffic, data. So you can focus on growth, not tech. Shorten, brand and track your links. Create clean, trackable, branded URLs. All managed from one place. Track everything that earns. From affiliate clicks to leadgen forms. Set dynamic payouts by action, partner or channel. Forms that do something. Create high-converting forms with post-submit logic. Route leads. Show offers. Trigger magic. Turn your traffic into a product. Sell leads smarter. Route them anywhere. Plug in any service to validate, enrich and monetize your leads. Live Data Feeds for Pre & Post-Conversion Touchpoints Keep (aggregated) data in sync across all sites and flows with a centralized, real-time feeds. Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features Real Results.Real People. Based on 10,000+ reviews on X PalDock has made managing leads and partnerships so much easier. We used to juggle different tools for tracking and lead generation, which made things messy. Now, everything’s in one place. We can collect, track, and manage leads and clicks all from the same software. It’s saved us a ton of time and let us focus on growing the business. Jiří Sillik CEO, Patron finance Monetizing display or link traffic has its limitations and doesn’t provide enough differentiation. We shifted our focus to delivering more value to our users and gaining a competitive edge. That’s when we started collecting leads and selling them through API to the highest successful bidder. PalDock handled all the technical heavy lifting, allowing us to concentrate on growing the business without getting bogged down by technical challenges. Martin Mazurek CEO, Converting As Affiliate Consultants, we've often seen clients struggle to start and grow their programs. We help them find the right solution and avoid common pitfalls. PalDock has been a great help, covering both current and future needs, and preventing the need for migrations to a more robust solution later on. Jan Stejskal Partner, Leadmarket Case study → We manage traffic through affiliate links and lead generation via API, and having both in one platform is a major advantage. With everything in a single dashboard, we gain full control of our affiliate channels and the flexibility to experiment and optimize more effectively. Since PalDock is designed for affiliates as well, integrating the standardized API is straightforward, allowing them to start sending leads within an hour. Simone Bertolone Director at Orka Ventures Browse Case Studies 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Dominate Your Industry with Our Unique Features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Why PalDock? You could duct tape five tools together. Or you could use one that actually works. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free Frequently AskedQuestions Why is Affiliate Marketing a Smart Business Strategy? The primary benefit of affiliate marketing is its effectiveness and cost efficiency. Partners earn commissions from their websites, followers, and other assets, while merchants gain valuable access to their user attention. Since merchants only pay for actual sales generated by affiliates, this model minimizes financial risk. Recommendations from trusted sources greatly enhance conversion rates, making affiliate marketing a powerful sales driver. How to choose the right affiliate management software? When selecting affiliate management software, start by analyzing the features you need right now and those you may require in the future. Avoid choosing a tool based solely on its price, as it may not meet your long-term goals and could face a costly migration later. Taking the time to evaluate your current and future needs will help you find a solution that effectively supports your growth and vision. Which affiliate marketing tools are important? Key affiliate marketing tools include robust and precise combination of cookie-based and cookie-less tracking for links, forms, and APIs, enabling effective performance monitoring through statistics. Providing affiliates with up-to-date promotional materials, accurate product feeds, and flexible commission structures with motivational bonuses (or penalties) helps drive sales. For service providers, lead generation features can be key to staying ahead of competitors and enabling affiliates to increase their volumes. What is affiliate marketing software? Affiliate marketing software is designed to track and report actions that trigger commissions, such as sales, leads, or clicks from affiliate links, forms, or APIs. In addition to these core functionalities, it provides other features like detailed reporting, automated commission calculations, and customizable promotional materials. Together, these capabilities form a comprehensive affiliate marketing platform that empowers both merchants and affiliate marketers to effectively sell products. When to Use Dedicated Software vs. Existing Affiliate Network? Dedicated software is ideal if you require customization, advanced features, full control, cost efficiency for high-volume traffic, data ownership, scalability for future growth, and independence from network restrictions. In contrast, existing affiliate networks offer a quick setup, access to a built-in pool of affiliates, lower upfront costs (though expenses will quickly rise as your program grows), and support resources. Insights that helps you grow Release Release notes 2026/08/14 This was a big one. We went through roughly 200 pages of our knowledge base and rewrote the whole thing. Clearer structure, consistent terminology, and… Read more: Release notes 2026/08/14 Release Release notes 2026/07/31 What’s new in PalDock? A lot of this month went into things you won’t see directly – query optimisation, indexing, and general tuning under the… Read more: Release notes 2026/07/31 Various Free Affiliate tracking software Many companies (inlcuding YOU) search for free affiliate tracking software because they want to launch an affiliate program without committing to expensive monthly fees. The… Read more: Free Affiliate tracking software Release Release notes 2026/06/30 We implemented numerous performance improvements and feature enhancements based on your feedback. We also significantly expanded the flexibility of the following features: The External Final Page… Read more: Release notes 2026/06/30 Release Release notes 2026/04/30 Based on your feedback, we’ve pushed the Integration Builder even further. We’ve rolled out a massive wave of UX fixes and performance updates. Here’s the… Read more: Release notes 2026/04/30 Features Lead Distribution Software Lead distribution software decides where each lead should go, sends it to the right buyer, and tracks the full process from intake to final delivery status. Read more: Lead Distribution Software See more #### PalDock’s use cases for Advertiser PalDock’s use cases for Advertiser Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro Running and scaling an Affiliate program is no easy task, especially when every industry has its own specialties. In the Loans sector? You’re probably looking at strong Lead generation features. Gambling? Detailed commission formulas and structures are key. And product comparisons? Dynamic banners and XML feeds are your friends. Everything you and your affiliates need in one place We dive deep into understanding what you need, crafting Paldock as the go-to solution for all things related to Affiliate marketing. We’ve got tools and features to support your activities. Let’s break down what we offer, from the simple stuff to the more advanced. Ready? Here’s what’s on deck: Affiliate marketing, lead generation & management – all in one place. Track accurately affiliate or any other traffic Efficiently Manage Your Affiliate Partners Connect with anything – traffic, stats, verification, enrichment. Always-Up-To-Date Marketing Assets Enhance Promotions with Advanced API Features Scale up with Lead generation Invoicing Made Simple Track Track accurately affiliate or any other traffic and conversions Track traffic from your affiliates and any of your campaigns seamlessly. Set clear attribution rules to avoid double-paying for a single conversion. Prefer your paid campaign to take precedence over affiliate sources? We’ve got you covered. Use either cookie-based, cookie-less tracking or promo codes for transparent and fair conversion attribution. View all your traffic and campaign data, not just affiliate insights, in a unified dashboard. Manage Efficiently Manage Your Affiliate Partners Seamlessly recruit, onboard, and organize your partners. Easily categorize and tag them, and assign dedicated affiliate managers for personalized attention. Tailor your commission structures to fit any model you desire – whether it’s CPA, CPS, revenue sharing, or any other or use a commission formula. Plus, boost partner’s motivation with the flexibility of offering one-time or automated bonuses, and apply penalties when needed. Effortless Notifications for You and Your Affiliates Stay updated with automatic or manual notifications tailored for both you and your affiliate partners. Whether it’s about a new partner awaiting approval, a fresh payout request, or even just general communications, we’ve got you covered. Beyond the standard alerts, customize notifications to suit specific needs. Worried about traffic drops from top affiliates or potential link/API downtimes? Set up specialized alerts and always be a step ahead in managing any challenges. Protect Your Brand with Our Safety Rules Knowing where your traffic originates from is essential. With Paldock gain a comprehensive insight into the delivered traffic, tracing back to the specific pages and websites it’s coming from. Not only that. You have the power to allow or disallow specific domains. So if a site doesn’t align with your brand’s values or raises concerns, you can swiftly block it. Or the other way around, you can accept traffic only from allowed domains. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Track Always-Up-To-Date Marketing Assets Take full control over your marketing assets with easy management of expiration dates and post-expiration content. Say goodbye to outdated banners or information on affiliate sites. Affiliates can enjoy the benefits of auto-updating HTML banners or tap into real-time product feeds – perfect for comparison websites. Manage Enhance Promotions with Advanced API Features Empower your affiliate partners by offering them enhanced API functionality. Let them promote your products with precision by allowing them to check through API who’s eligible for your offerings. With our adaptable API, affiliates can easily verify details like location or user group eligibility before directing potential clients to you. It’s an ideal solution for services like internet connectivity and other products, which are not for everyone, everywhere. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Boost effectiveness and revenues by Lead generation Go beyond clicks and tap into leads as a valuable traffic source, all tracked in one platform. Give affiliates customizable embed forms or API access for direct lead submissions. Build the ideal lead journey with our drag-and-drop editor featuring validation, verification, and advanced filtering. If your affiliate already uses Paldock, setup can be seamless and save weeks of integration work. Invoicing Made Simple Receive invoices from your affiliate partners or let Paldock auto-generate them on their behalf. We’ve got the checks and balances in place to adjust their account balances accurately, ensuring seamless payments every time. Got internal rules about the number of invoicing partners? No worries. We can consolidate everything, making Paldock your single point of contact for invoicing. Dominate Your Industry with Our Unique Features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free #### PalDock’s use cases for Affiliate partner PalDock’s use cases for Partners Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro Hey there, fellow affiliate enthusiasts! Whether you’re an influencer, blogger, or any kind of affiliate partner – be it a veteran or someone just starting out – we know everyone has their unique way of doing things. The good news? PalDock’s got your back no matter your style or stage. Everything you need in one place From the first step in your affiliate journey to growing a full-blown network, we’ve got tools and features to support you every step of the way. Let’s break down what we offer, from the simple stuff to the more advanced. Ready? Here’s what’s on deck: Promo code tracking URL shortening Link management Cookie-less tracking Products data aggregation Conversion tracking Lead generation Scaling into Affiliate network Track Promo code tracking – Not only for influencers Looking to collaborate with advertisers without broadcasting that you’re earning commissions through affiliate cooperation? Or maybe your platform isn’t too keen on affiliate links, or your followers just aren’t fans of them? That’s where promo codes come into play. With our system, you don’t need visible affiliate links. Get your personal promo code, and when someone uses it, that success is linked right back to you (even if your competitor tries to use it)  No cookie tracking is needed. Our promo codes sidestep the usual cookie issues, ensuring your traffic is always tracked. Manage Boost Clicks with the fastest URL shortener to create short branded links Lengthy, messy links can seriously harm your click-through rates. People either hesitate to click on them or get stuck in slow redirects. Paldock’s here to change the game. Turn those lengthy URLs into neat, branded links that represent your website with grace. With a direct connection to both your site and advertisers, we ensure super-fast redirects, beating any other URL-shortening tools. And the icing on the cake? Change a shortened link once, and it updates across multiple sites. No tedious, site-by-site changes. A real time-saver! Effortless Link Management Juggling multiple affiliate links or websites? Things can get tangled fast. That’s where Paldock steps in. Centralize and manage all your affiliate links from a single hub, eliminating the hassle of going through countless posts or sites to make link updates. But we don’t stop there. We actively monitor link health, ensuring users are smoothly redirected to an alternative you’ve set up if a link breaks. And, of course, we’ll promptly notify you.  Bring your revenues back with Cookie-less tracking Did you know? Up to 64 percent of global consumers agree that they accept all cookie permissions when prompted but rates vary by region according to YouGov’s global consumer study. If your advertiser relies solely on cookies, that’s a whopping 40% of potential revenues slipping away from you. But Paldock has a solution. With our Postback tracking, we bypass cookies altogether, ensuring every conversion and every cent is captured. PalDock ensures every possible dollar lands in your pocket. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Track Automate Product Data with Advanced Aggregation Product comparison is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds including your own for easy comparison on your sites. The best part? Updates sync automatically with advertiser XML changes, but you also have the flexibility to tweak things manually.  Manage Centralize Your Conversion Insights Drowning in data from a multitude of advertisers and networks? Bouncing between systems to keep tabs on conversions can be overwhelming. Paldock simplifies it all. We bring together results from every corner into a unified dashboard. Just one login, one platform, and you have it all at your fingertips. And if your advertisers use Paldock as well? Even better! Generate promotional content or send out invoices directly, no need to toggle between accounts. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Boost Your Earnings with Lead Generation Sending clicks to advertisers is decent, but let’s face it, it’s like throwing darts in the dark. You can’t really steer the conversion once it’s on their website. Here’s where Lead Generation shines. Instead of just routing clicks with unpredictable outcomes, why not gather leads directly on your site and pass on this valuable data? It’s a win-win-win! Your visitors get extra value, you grow a robust database, and essentially, you’re crafting your very own product and the Advertiser is happy for a hot lead. Think about it: if you’re promoting services, say loans, you can collect user info and match them with the perfect loan offer. The result? A significant revenue increase, as a solid lead far outvalues a mere redirect. Scale your business and start your own Affiliate program Thinking big? Considering running your own affiliate program or even an entire network in the future? It’s crucial to pick a platform that not only offers the features we’ve covered before but also empowers you to oversee your very own affiliates. Dive into recruiting, customize commission rates or tiers, and explore many more possibilities. Set your sights on scaling up with the right tools in hand so you don’t have to difficultly change them later. Dominate Your Industry with Our Unique Features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free #### PalDock’s use cases for Network PalDock’s use cases for Network Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro Balancing Affiliates and Advertisers can feel like an endless game of mismatch: sometimes too many affiliates, other times overflowing with advertisers. With uncertain network value on a decline, affiliates are often going straight to advertisers. That’s where we step in. Paldock allows you to elevate above standard offers, giving you more than just mediating clicks. We amplify your offerings, adding genuine value for your affiliates. And if you’re also driving traffic on your own, you will love what Paldock has in store for you.  Everything you and your affiliates need in one place We dive deep into understanding what you need, crafting Paldock as the go-to solution for all things related to Affiliate marketing and running a Network. We’ve got tools and features to support your activities. Let’s break down what we offer, from the simple stuff to the more advanced. Ready? Here’s what’s on deck: Accurate tracking Manage Your Partners Effortless notifications Cookie-less tracking Products data aggregation Lead generation Grow into a broker Invoicing Made Simple Track Track accurately affiliate or your own traffic and conversions Whether it’s from affiliates or your own campaigns, monitor all traffic effortlessly. Define your attribution rules—whether prioritizing your own sources over affiliates or opting for a last-click attribution. Use cookie-based and cookie-less tracking, or utilize promo codes for clear and fair conversion tracking. View all traffic, conversions, and campaign data in a unified dashboard across all partners, advertisers, and your own campaigns. Manage Harness full SEO potential and retarget every click Have a flagship branded website driving traffic? Use it to its fullest by turning it into an SEO-boosting redirect hub. By using a 301 permanent redirect from affiliates to your domain and then a 302 temporary redirect to your advertisers, you harness all the SEO benefits from your affiliate links. Worried Google might flag them as affiliate links, given its skill for recognizing standard affiliate link structures? Design your own unique tracking parameters to fly under the radar. Bonus: Embed your remarketing pixels within these redirects, letting you capture, segment, and retarget those affiliate-driven clicks for your maximum revenues. Efficiently Manage Your Affiliate Partners and Advertisers Start strong with smooth recruitment and onboarding of partners or advertisers, then categorize, tag, and allocate dedicated managers to ensure personalized handling. Customize commission plans – be it CPA, CPS, revenue sharing, or any other model (including custom formulas). You can also set distinct commission models for partners and advertisers. Keep the motivation high with occasional bonuses or go for regular, automated incentives. And if there’s a slip-up, there are penalties in place.  Effortless Notifications for You and your Affiliates and Advertisers Stay updated with automatic or manual notifications tailored for both you and your affiliate partners and advertisers. Whether it’s about a new partner awaiting approval, a fresh payout request, or even just general communications, we’ve got you covered. Beyond the standard alerts, customize notifications to suit specific needs. Worried about traffic drops from top affiliates or potential link/API downtimes? Set up specialized alerts and always be a step ahead in managing any challenges. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Track Protect Brands with Our Safety Rules For advertisers keen on brand protection, you can provide traffic exclusively from whitelisted domains based on their choosing. With Paldock, they’ll also be able to pinpoint the exact page from where the traffic originates, facilitating their possible review process. Furthermore, if required, affiliate partners can be prompted to sign the extra advertiser’s terms and conditions. And should advertisers wish to have a hands-on approach, you can enable them to communicate with and manage affiliates directly. Manage Boost effectiveness and revenues by Lead generation Think beyond just clicks! Dive into leads as a powerful traffic source and track everything on a single, unified platform. Make the process more efficient: equip affiliates with ready-to-embed customizable forms for their sites or an API for direct lead submissions to Paldock, and, ultimately, to you. Craft the perfect lead journey with our intuitive drag-and-drop editor, packed with lead validation, verification, and advanced filtering. Bonus: If your affiliate is already on Paldock, you’re in for a smooth setup, potentially saving weeks of API integration time. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Build your own products to get an edge over competitors Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Considering a Product or Service Comparison? How about a recommendation engine tailored to user inputs? Whatever you envision, we’ve got the tools. Integrate with Advertisers via API, gather all the essential data, and turn those connections to your advantage. Invoicing Made Simple Receive invoices from your affiliate partners or let Paldock auto-generate them on their behalf. Our system ensures precise balance adjustments for smooth transactions each time. Easily produce invoices for advertisers via Paldock and monitor their payment status. This is especially handy when affiliate partners must first wait for advertisers to settle with the network before their commissions get approved. Dominate Your Industry with Our Unique Features Choose your industry to explore how Paldock helps businesses like yours grow faster, perform better, and stay ahead of the curve. Loans Telecommunications eCommerce iGaming Comparators Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free #### Partnerize Alternative What is Partnerize? Partnerize is an enterprise platform aimed at big brands and agencies running large-scale affiliate and partnership programs. It offers a wide range of features and integrations, but the system feels bloated and overly complex for everyday use. The interface is dated, onboarding is lengthy and even simple tasks often require support involvement. While Partnerize provides strong analytics and network reach, its rigidity and steep learning curve make it impractical for most mid-sized or fast-moving companies. It is powerful on paper but heavy in execution. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Partnerize vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: PartnerizePalDockTracks affiliate linksLead generationLead distributionAdvanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### PartnerStack Alternative What is PartnerStack? PartnerStack is popular with SaaS vendors because of its polished interface, subscription-friendly commission logic and a built-in marketplace where affiliates can discover programs. For SaaS startups it feels turnkey, since the platform handles payouts and onboarding without much ops work. The issue is scope and cost. PartnerStack focuses almost entirely on very standard affiliate program features like link tracking, referral reporting, recurring commissions and does not support lead handling and complex commission formulas. Yet despite offering only the standard, it is one of the most expensive affiliate platforms on the market, charging both a high subscription fee and a cut of your program’s revenue. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → PartnerStack vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: PartnerStackPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Phonexa Review and Alternatives Disclaimer: This review isn’t based on a quick demo. We spent months managing Phonexa for one of our client, dealing with it daily. What we’re sharing is our raw, unfiltered experience. If we sound critical, it’s not to bash the competition. It’s the honest perspective of someone who had to actually make the system work. What is Phonexa? Phonexa is an over-a-decade-old, US-based platform that started with a call tracking and grew over last decade when there were few alternatives. Today, the platform’s age shows. While it performs well for call tracking, its affiliate marketing and lead generation features deserve an upgrade. The platform can feel like a collection of modules bolted together later. Even though some features are powerful. For example, you can Approve/Reject affiliate transactions in Lynx (for link traffic), but not in LMS Sync (for lead traffic). While Phonexa offers many features, it is sometimes unnecessarily complex (their documentation rarely saves you from having to contact support) and difficult to adapt to the needs of modern businesses. Below, we explore Phonexa’s features and key limitations in detail and compare them directly to our PalDock. For businesses that rely on lead distribution or affiliate tracking, these gaps often become a major bottleneck. We built PalDock as a purpose-built alternative to solve these exact problems. Pros and Cons of Phonexa Pros: + Solid call tracking with granular detail+ Can do call tracking, affiliate link tracking and lead generation tracking in one tool+ Supports a wide range of advertiser APIs, but struggles with anything beyond a simple two-step ping and post.+ Affiliates can use both the API and embedded forms+ Responsive and helpful support Cons: – Affiliate and lead generation features are inconsistent– Overcomplicated UX where affiliates get lost easily and even simple tasks require too many steps and time– Limited customization and localization (only English language and USD/GBP currency in our setup)– Fragmented logic with separate modules for links and leads and no unified conversion view– Lead generation module does not support a Pending conversion approval workflow. You can’t hold individual conversions for later approval or rejection– Cannot combine pixel tracking and S2S postback tracking, you have to pick only one which is problematic because their pixel tracking can measure affiliate traffic inaccurately, as explained below.-No support for first-party pixel tracking, leading to a 50% drop in measured affiliate traffic for one of our clients’ affiliate programs– Incomplete documentation/knowledge base that’s hard to navigate, leading to constant back-and-forth with support. An Affiliate Experience Stuck in the Past The affiliate registration form feels outdated, and every default value is set to the US, even if your offer is not based there. These settings can’t be changed, so affiliates are forced to scroll through a list of 250 countries and phone prefixes just to complete the form. The worst part is that you cannot customize the form fields or even add a simple ‘I agree with the Terms and Conditions’ checkbox. See for yourself below and compare Phonexa to its alternative: PalDock, where you can fully customize your forms exactly how you need. Another issue is the login experience. When affiliates log in, they land on a “dashboard” showing modules like Lynx and LMS Sync – terms most have never heard of. It’s again not much customizable. Since these modules are independent, many things work completely differently inside, which confuses both affiliates and even admins. So instead of a clean dashboard, users are greeted with a confusion. List of offers is fine The list of offers, on the other hand, is decent and provides all the necessary information. Setting aside the fact that admin-only alerts (like ‘maximum 100 offers’) are unnecessarily visible to affiliates. The good thing is that affiliates can generate their unique tracking links with a single click directly from the listing. It fully supports custom parameters and deep links. This part works exactly as it should. Offer details do not have enough… details Things get worse once you click into an individual offer. Affiliates are stuck with a generic, auto-generated table that admins can’t customize much. It offers very limited control over how detailed descriptions, media assets, and promotion rules are presented – the exact information affiliates need to start. Once an affiliate starts running traffic, they will want to track their performance. Phonexa handles this well, offering a variety of reporting options and a detailed conversion breakdown. Where Simple Tasks Become Unnecessarily Complicated The admin side is just as disorganized as the affiliate portal, only with more unnecessary clutter. Modules like HitMetrix or E-Delivery do not even make sense to use when there are modern alternatives like HotJar and Mailchimp. The most frustrating part is the Books360 module. Invoicing and payments are essential to affiliate management, yet Phonexa have them in a separate module just to handle basic billing. Where Productivity Goes to Die After over a year of using Phonexa, we were constantly frustrated with little things that should take 30 seconds, but Phonexa takes you on a full 15-minute, multi-step journey where the chance of making a mistake is absurd. Here are the daily frustrations that make you want to throw your monitor out the window: Lead-Loss by Accident: Want to receive leads from an affiliate? You have to manually whitelist every single domain they use. There is no “allow by default” option. If you miss one, your leads go straight to the trash, and you won’t even notice until the money is gone. Confusing Navigation: You won’t find “Lead Export” in the Lead Logs. No, it’s hidden in System Management. Because that makes sense… to absolutely no one. The 6-Month Nightmare: If you need an export of the last 6 months, Phonexa gives you 6 separate files instead of one unified export. Why? Apparently, one file would be too easy. 10 Minutes of Clicking: A simple export involves a 10-minute odyssey of clicking, naming products, authorizing, and waiting. Another frustrating thing is the data fragmentation. Performance is trapped in isolated silos: calls, clicks, and leads don’t come together in one unified dashboard. Without a unified dashboard, cross-channel analysis becomes a manual spreadsheet nightmare. “A good platform should be self-service. Phonexa is the opposite. You have to reach out to support for every little thing. Honestly, at this point, I see their support team more than my own mother.” From Fields to Distribution: The Lead-Gen Essentials But let’s focus on what is really important for standard Phonexa customers: defining form field structures, creating forms from those fields or integrating them through API, and building advertiser integrations to be used in the Ping-tree distribution. Defining the form field structure Determining which data to collect manually and which to enrich or validate via third-party services. Unfortunately, Phonexa doesn’t let you freely call arbitrary external APIs for data enrichment; you’re largely limited to supported or pre-built services. In PalDock, however, you can automatically pull data from public databases so you don’t have to ask users for it. You can also validate anythign such as phone numbers, emails, or national IDs in real-time and use autosuggest to help user fill in precise input without typos. Build your forms Once your fields are ready, you’ll likely want to build an embeddable multi-step form. Phonexa actually handles customization quite well and offers plenty of options, but its outdated architecture is starting to show. It lacks modern UX, which often requires a ticket to Phonexa support for a custom edit. The real trouble, however, is the embedding process. Phonexa uses a Javascript-based implementation that is a total headache. It requires loading four separate scripts: the form itself, mobile compatibility, parameter tracking, and error translations. To make matters worse, the form isn’t isolated, so any CSS on the affiliate’s website can easily break the layout. PalDock takes a smarter approach. Instead of a fragile multi-script mess, it provides a modern, isolated embed that works perfectly out of the box. Integrating dozens of buyers The single most important feature of any lead generation tool is buyer integration, as APIs vary incredibly from one partner to another. Phonexa is relatively strong in this area, but coverage depends heavily on the GEO and on whether integrations in that market use a simple two-step flow or require more complex multi-step integrations. However, the rest must be handled manually by Phonexa IT. While you get some integrations for free, every additional one costs $149. The main problem is that Phonexa’s builder only supports a two-step process: (pre)Ping and Post. In reality, many modern integrations require three, four, or even more steps, often involving webhooks or polling loops to wait for specific results. These complex workflows are well beyond Phonexa’s current capabilities. This is where we have to take pride in what we’ve built: our Integration Builder in PalDock is incredibly flexible. After managing hundreds of unique API integrations, we have yet to encounter a single one that was impossible to implement. Selling leads via Ping-Tree Once your fields are defined and integrations are ready, you need to sell your leads for the best price. That is where the Ping-tree distrbution comes in. It’s the brain of your operation, ensuring every lead is sold for the highest price. While Phonexa supports standard models like exclusive sales and multi-sell, it lacks support for Ping-Pick-Post distributions. The post-sale user experience is also limited. Phonexa can redirect a user to a URL received from the advertiser or show a basic thank-you page, but we could not build a “Result Page” that displays results from multiple successful advertisers at once. Client story From the very beginning, the client’s onboarding experience was a struggle. Although Phonexa’s team was responsive, detailed answers required digging through a poorly structured and incomplete knowledge base. They spent hours looking for solutions that should have been easily accessible. To make things worse, they were initially assigned to the US support team, without being told that a UK team existed. Weeks were lost due to time zone delays before they discovered the UK support office by accident. At no point were they informed of this by Phonexa. “Basic things were unnecessarily complicated“ “On paper, Phonexa checked all the boxes during our vendor selection. But once we started the implementation, we realized that many features only work through awkward workarounds or not at all in real use. The platform is complex, but not intuitive for affiliate partners, which results in higher support needs and significantly more time spent on management tasks that should be simple.” “On paper, Phonexa checked all the boxes during our vendor selection. But once we started the implementation, we realized that many features only work through awkward workarounds or not at all in real use. The platform is complex, but not intuitive for affiliate partners, which results in higher support needs and significantly more time spent on management tasks that should be simple.”“Basic things were unnecessarily complicated. Features that are standard in other platforms were either missing or designed in a way that made them unusable. For example, creating affiliate accounts was incredibly time-consuming. On other platforms, importing 40 partners takes about 5 minutes. With Phonexa, we had to manually click through each one, following an overly complex flow and do it separately for link and lead module. That means the same repetitive work had to be done twice, taking up nearly 2 hours instead of 5 minutes. We wanted to use our own subdomain, but that would’ve cost us an extra $200/month. The currency couldn’t be changed, everything was shown in GBP despite us working with local currency. There was no localization support, no local language, no support for diacritics or any customizations.” Jan Stejskal Affiliate marketing consultant Case study → Ultimately, while they technically completed the integration, it became clear that Phonexa was not viable for long-term use. The interface confused their partners, core features were split across multiple modules, and conversion tracking was inconsistent and limited. They wanted to track multiple lead stages throughout the process and assign different payouts to affiliates based on those stages, not just “Lead Created.” However, that wasn’t possible, so they had to settle for basic tracking and abandon more advanced logic. After a thorough evaluation and growing inefficiencies, the client decided to leave Phonexa. Want to discover other areas where Phonexa falls short? Check the comparison below. Phonexa vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: PhonexaPalDockTracks affiliate links, embedded forms and API leadsAll traffic channels (link, forms, API) in one dashboardAdvanced lead handlingAdvanced trackingCommission levels with different paid goalsConversion approval⚠️Multiple languages and currencies The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → Tracks affiliate links, embedded forms and API leads Phonexa and PalDock are among the very few tools in the world that support tracking affiliate link clicks, embedded forms, and API-based lead delivery within a single platform. But even in this small group, not every tool does it well. Phonexa is fairly capable in this area but it would benefit from advanced features such as flexible lead validation or field modification before sending. If forms and API-based leads are important to you, choosing the right tool is crucial. Make sure to pay close attention to all the specific features related to lead handling and delivery. All traffic channels (link, forms, API) in one dashboard Having all traffic channels such as affiliate links, embedded forms and API leads in one unified dashboard is a huge advantage. Whether you are an admin or an affiliate, you can instantly see all performance data in one place without switching between different sections or searching through multiple reports. It saves time, reduces confusion and gives a clear overview of what is working. For admins, it improves decision-making. For affiliates, it makes tracking results easier and more transparent. Advanced lead handling In Phonexa, you can map fields from Phonexa to a third party API integration, including select boxes with multiple predefined options (called “array mapping” in Phonexa). However, your options for modifying those fields and their values are very limited. You can apply basic conditions to decide whether a field should be sent, but the options to transform the data are very limited. This becomes a problem when the third party requires a specific format or when you want to adjust the data to better sell the lead. See our article on How to handle leads. Advanced tracking In Phonexa, you can’t combine pixel tracking and S2S postback tracking to maximize traffic attribution, which is an industry standard that allows cookie-based and cookieless methods to complement each other. In Phonexa, you’re forced to choose one or the other. That is problematic because Phonexa pixel tracking also uses only 3rd party tracking which is unrealiable. One of our clients’ affiliate programs saw 50% drop in measured affiliate traffic after moving to Phonexa and using their tracking pixel. They had to replicate the entire first-party pixel tracking setup on their side (and use postbacks instead) just to use the tool. Commission levels with different paid goals Setting commission tiers in Phonexa is technically possible, but only if you’re on the enterprise plan. Even then, it’s not really usable. One of our client tried to build a setup with 12 products like mortgage, insurance, utilities etc., each having four statuses: lead created, validated, processed, and sold. The idea was to pay different affiliates based on trust. Those they trusted most would be paid for lead created, which is evaluated instantly. Less trusted partners would get paid only for lead sold (meaning the contract was signed), which for some products might take over a month. Others would fall somewhere in between. For affiliates buying traffic, getting the commission as soon as possible is crucial to maintain their volumes. In theory, that’s doable. But in Phonexa, all goals are visible to affiliates. That means every affiliate sees the entire list – in this case 48 goals (12 products times 4 statuses), even if only 12 apply to them. It creates total confusion. Affiliates start asking why they see 48 goals, why they’re not paid for certain ones, and so on. Technically, Phonexa supports multiple goals, but in practice it’s nearly impossible to manage cleanly. On top of that, this setup only works in the LYNX module for affiliate links, not in LMS Sync, which handles leads. Conversion approval If you are surprised that affiliate marketing software which should at its core handle commission approval and payouts cannot mark conversions as approved or rejected then welcome to the club! Phonexa lacks a conversion approval workflow in its LMS module. You cannot set conversions to pending and approve or reject them later. That option is only available in the Lynx module via the conversion approved period setting. What is more, Phonexa does not track which conversions have already been paid out (LMS conversion does not have this status). There is no built in paid or unpaid status for conversions. If you force affiliates to get paid every month so you know payouts are complete, that might work. Until an affiliate wants to move payment to the next month or forgets to invoice. Then you’ll need to keep everything organized in a some excel spreadsheet so you don’t accidentally pay the same conversions twice. Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Who is Phonexa (not) for? One of the typical problems with big, US-based companies is that growth and revenue come before client needs. Unlike their competitor, Tune, who at least offers customizations (albeit at a premium), Phonexa doesn’t support much customization, such as localizing the affiliate sign-up page. But if you’re a company based in the US or UK focusing on call tracking, Phonexa might be the right tool for you. If you’re not planning to do anything ambitious with affiliate or lead gen, their features should be enough. Phonexa Pricing Phonexa no longer publishes its plan pricing publicly and currently asks prospective customers to request a custom quote. For context, when we used and reviewed Phonexa, its publicly available pricing started at $250/month with a $500 setup fee for the Lite plan. The Enterprise plan was $1,000/month with a $2,000 setup fee and included features that were not available on the lower tiers. These figures are historical and should not be treated as Phonexa’s current pricing. Since pricing is now provided on request, you’ll need to contact Phonexa directly for an up-to-date quote. Moving from public pricing to custom quotes also gives Phonexa much more flexibility over what individual customers pay. Companies often make this kind of change when they want more room to increase pricing, although only Phonexa knows whether that is the reason here. One thing to be aware of: if you request to switch your support team from the US to the UK, your monthly fee may be billed in GBP instead of USD, effectively raising the price by about 25%. Something to keep in mind, especially if you’re based in Europe. Summary Phonexa has plenty of flaws and half-baked features, but it’s one of the very few platforms in the world that supports lead generation through embedded forms and API for collecting and distributing leads. That’s its biggest strength. Phonexa is unfortunately missing some basic features that every affiliate platform should have, like conversion approval, flexible payout goals, and more. If you don’t need lead generation tools, you’re better off looking elsewhere. If you do, get ready to deal with a lot of annoying problems. #### Plat Alternative What is Plat? Plat.com is an older click and lead tracking platform that hasn’t evolved much in recent years. It covers the basics like event tracking, lead routing and simple reporting, but the overall experience feels dated and limited. The interface is functional but far from modern, and most features are focused purely on tracking rather than managing affiliate relationships. Pricing scales quickly with volume, which makes it expensive for sustained use. For basic tracking needs it still does the job, but for any serious or scalable affiliate setup it feels like a relic of an earlier generation. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Plat vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: PlatPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Pricing Free with every feature unlocked Free affiliate marketing software that grows with you. Profit-Based Pricing. Pay only from approved payouts. Get 2 months free with annual billing. Try for Free → Want to talk or get a live demo? Get in touch → The more you make, the LESS you pay! Select your expected monthly approved in-house or affiliate payouts to calculate your final price Approved Payouts ? Revenue Share ? Total Cost ? Approved Payouts ? Revenue Share ? Total Cost ? USD EUR Try for Free → Real Results.Real People. Based on 10,000+ reviews on X PalDock has made managing leads and partnerships so much easier. We used to juggle different tools for tracking and lead generation, which made things messy. Now, everything’s in one place. We can collect, track, and manage leads and clicks all from the same software. It’s saved us a ton of time and let us focus on growing the business. Jiří Sillik CEO, Patron finance Monetizing display or link traffic has its limitations and doesn’t provide enough differentiation. We shifted our focus to delivering more value to our users and gaining a competitive edge. That’s when we started collecting leads and selling them through API to the highest successful bidder. PalDock handled all the technical heavy lifting, allowing us to concentrate on growing the business without getting bogged down by technical challenges. Martin Mazurek CEO, Converting As Affiliate Consultants, we've often seen clients struggle to start and grow their programs. We help them find the right solution and avoid common pitfalls. PalDock has been a great help, covering both current and future needs, and preventing the need for migrations to a more robust solution later on. Jan Stejskal Partner, Leadmarket Case study → We manage traffic through affiliate links and lead generation via API, and having both in one platform is a major advantage. With everything in a single dashboard, we gain full control of our affiliate channels and the flexibility to experiment and optimize more effectively. Since PalDock is designed for affiliates as well, integrating the standardized API is straightforward, allowing them to start sending leads within an hour. Simone Bertolone Director at Orka Ventures Browse Case Studies Feature List Key FeaturesRevenueUnlimitedAffiliate PartnersUnlimitedAdvertisersUnlimitedOffersUnlimitedClicksUnlimited*LeadsUnlimited*ConversionsUnlimitedTransactionsUnlimitedAffiliate and Offer marketplace * Subject to fair use and technical limits as described in the Terms of Service. In other words, we reserve the right to review and adjust usage for clients whose usage is disproportionate to their plan. On-Demand Services ServicePriceAPI integrations done by the PalDock team5 free, then €200 eachCustom feature development€200/h; €100/h if shared featureAffiliate invoice consolidation3% of amount (min. EUR 50) Why Choose PalDock over Others?See How We Compare! Best Tune AlternativeBest CAKE AlternativeBest Post Affiliate Pro AlternativeBest Affise AlternativeBest Tapfiliate AlternativeBest Phonexa AlternativeBets MyAffiliates AlternativeBest LeadDyno AlternativeBest Affilbox Alternative Best Voluum AlternativeBest Trackier AlternativeBest RedTrack AlternativeBest Partnerstack AlternativeBest AffiliateWP AlternativeBest Rewardful AlternativeBest Scaleo AlternativeBest Uppromote AlternativeBest Refersion Alternative Best Everflow AlternativeBest FunnelFlux Pro AlternativeBest Binom AlternativeBest FirstPromoter AlternativeBest WP Affiliate AlternativeBest Solid Affiliate AlternativeBest Kiflo AlternativeBest Partnerize AlternativeBest Impact AlternativeBest Plat Alternative Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Frequently AskedQuestions Why is Affiliate Marketing a Smart Business Strategy? The primary benefit of affiliate marketing is its effectiveness and cost efficiency. Partners earn commissions from their websites, followers, and other assets, while merchants gain valuable access to their user attention. Since merchants only pay for actual sales generated by affiliates, this model minimizes financial risk. Recommendations from trusted sources greatly enhance conversion rates, making affiliate marketing a powerful sales driver. How to choose the right affiliate management software? When selecting affiliate management software, start by analyzing the features you need right now and those you may require in the future. Avoid choosing a tool based solely on its price, as it may not meet your long-term goals and could face a costly migration later. Taking the time to evaluate your current and future needs will help you find a solution that effectively supports your growth and vision. Which affiliate marketing tools are important? Key affiliate marketing tools include robust and precise combination of cookie-based and cookie-less tracking for links, forms, and APIs, enabling effective performance monitoring through statistics. Providing affiliates with up-to-date promotional materials, accurate product feeds, and flexible commission structures with motivational bonuses (or penalties) helps drive sales. For service providers, lead generation features can be key to staying ahead of competitors and enabling affiliates to increase their volumes. What is affiliate marketing software? Affiliate marketing software is designed to track and report actions that trigger commissions, such as sales, leads, or clicks from affiliate links, forms, or APIs. In addition to these core functionalities, it provides other features like detailed reporting, automated commission calculations, and customizable promotional materials. Together, these capabilities form a comprehensive affiliate marketing platform that empowers both merchants and affiliate marketers to effectively sell products. When to Use Dedicated Software vs. Existing Affiliate Network? Dedicated software is ideal if you require customization, advanced features, full control, cost efficiency for high-volume traffic, data ownership, scalability for future growth, and independence from network restrictions. In contrast, existing affiliate networks offer a quick setup, access to a built-in pool of affiliates, lower upfront costs (though expenses will quickly rise as your program grows), and support resources. #### Privacy policy Privacy policy This Privacy Policy forms an integral part of General Terms of Service. Any term used in this Privacy Policy not explicitly defined herein shall be interpreted according to the General Terms of Services.  No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Who are we? We are Leadgen Labs s.r.o., company registered in the commercial register maintained by the Municipal Court Prague, Section C 247987, identification number 04458206, with its registered seat at Příčná 1892/4, 110 00 Praha, Czech republic (hereinafter referred to as the “Provider” or „we“). Who does this Privacy Policy apply to? This Privacy Policy applies to: representatives and users of our customers (“Tenants”) who access the Application on behalf of a Tenant; and Users invited by a Tenant to access the Tenant’s space in the Application, such as Affiliates or advertisers. In all such cases, you are a data subject whose personal data may be processed in connection with the use of the Application. Why may we need to process your personal data? We provide our customers (hereinafter referred to as the “Tenants”) with a web-based application that is used for tracking Tenants’ advertising activities in the area of affiliate marketing (hereinafter referred to as the “Application”), primarily, but not only, to help market Tenants’ services or products online on third-party websites by advertisements (those third parties hereinafter also referred to as the “Users”). To be able to do so, we need to process some personal data. Whether, and to what extent, we process personal data may depend on the package of services selected by the Tenant and on how the Tenant uses the Application. We process personal data where necessary for the performance of a contract or in order to take steps at your request prior to entering into a contract and to meet legal requirements, above all but not limited to accounting and tax legislation. For personal data that Tenants submit to or generate in the Application, including data about their Users and end customers, the Tenant is the controller and the Provider acts as the processor. For account and relationship data of Tenant representatives and invited Users (such as login details, contact details, roles and permissions), and for service logs, security and billing identifiers needed to operate and protect the Application, the Provider acts as an independent controller. What does GDPR mean?  GDPR stands for Regulation EU 2016 slash 679 of the European Parliament and of the Council on the protection of natural persons with regard to the processing of personal data and on the free movement of such data. GDPR represents the legal framework for the protection of personal data in the European area and directly establishes the rules for the processing of personal data. The Provider is governed by the GDPR rules in its activities and is compliant with the GDPR. What personal data we may have access to?  The scope of personal data depends on how the Tenant uses the Application. In general we may process settlement and billing data required to administer payments and comply with legal dutiesWhere we process Tenant program and payout data we act as a processor for the relevant Tenant. Where we process diagnostic and security data that are necessary to operate the service we act as an independent controller. account and relationship data needed to provide access and support technical and usage data generated by the Application for operation, security and performance Service communications and product updates We may use your contact details (such as your email address) to send you: service and transactional communications that are necessary to operate your account and the Application (for example account creation, security alerts, important product or terms updates); and occasional information about updates and improvements to the Application based on our legitimate interest in informing users about relevant changes to our services. Service and transactional communications are sent on the basis of contract performance or our legitimate interest in operating a secure and reliable service and you cannot opt out of messages that are necessary for the functioning or security of your account. You can object at any time to receiving emails about updates, improvements and new features by using the unsubscribe link in any such email or by changing your preferences in your account settings. How do we protect personal data?  Taking into account the state of the art, the nature, scope, context and purposes of processing personal data as well as other factors, the Provider has implemented appropriate technical and organizational measures in order to ensure the level of security appropriate to relevant identified risks.  The Provider shall always process personal data only lawfully, fairly and in a transparent manner in relation to the data subject. Personal data are collected for specified, explicit and legitimate purposes and not further processed in a manner that is incompatible with those purposes. The scope of personal data collected shall be adequate, relevant and limited to what is necessary in relation to the purposes for which they are processed. The Provider may use a third party to further process some personal data, especially technical partners. In such a case the Provider will announce relevant information about such a partner on his website www.paldock.com. The Provider shall store any personal data within the Tenant’s region, be it the European Union or the United States. How long will we have access to personal data? The Provider processes personal data for the purpose of performance of the contract with the respective Tenant and therefore processes personal data for the duration of the contractual relationship. After its end, the Provider may retain personal data for a limited period where required by law or where necessary to resolve disputes, enforce agreements or comply with other legal obligations. The Provider may also retain limited records necessary to demonstrate compliance and service integrity, including records of notices delivered, acceptances captured and communication preferences, for a reasonable period consistent with statutory limitation periods and the Provider’s retention schedule. What are your rights regarding your personal data? We always process personal data in a transparent and correct manner and in accordance with the legal requirements. However, at the same time you have the right to contact us in order to obtain information about your personal data processing or to exercise the rights that are related to personal details. Above all, but not only you have the right to obtain the copy of your personal data processed by the Provider, you have the right to request an update of your personal data if you believe them to be inaccurate, you have a right to request from us the erasure of your personal data if they are no longer required for the purpose for which they were processed. You have a right to data portability. You have a right to object to the processing of your data.  You have a right to file a complaint with the supervisory authority (Office for Personal Data Protection) should you think that the rules of personal data protection were breached during the processing of your personal data.  Office for Personal Data Protection, Pplk. Sochora 27, 170 00 Prague 7, www.uoou.cz  For more information about the Provider’s data protection processes please contact us anytime at dpo@paldock.com. #### Product comparison Affiliate software Affiliate software for Comparators Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry. No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Key Features to Look for in Software for Comparison sites If you run a comparison project and want to succeed, you need a tool that boosts clicks with a branded shortener, makes link management effortless, optimizes paid ads with precise click tracking, and tracks all traffic and conversions while automatically generating banners from your data feed. To deliver even more value, you can build your own product with lead generation and scale further by running your own affiliate program. All-in-one platform Affiliate links, forms, APIs, and Conversions. All in one place. Smarter data feeds Aggregate, edit & sync XML/API feeds across unlimited sites. Partner management Manage and categorize publishers and advertisers in one place. Powerful API Connect with anything with no developer needed. Cookie(less) tracking Multiple tracking methods for the most accurate results. Embedded lead forms Collect leads straight from affiliate sites – no redirects. Flexible commissions Set custom formulas, tiers, bonuses & penalties. Unified view of ROI Import costs, refunds, and revenue. See the full picture. Try for free Track Cookie-less Tracking Tracking might sound basic, but in comparators it quickly becomes complex. Cookie tracking fails when orders are not approved instantly or when the product is processed through a call center. Clients often need verification or a follow-up, which makes cookie-based tracking unreliable. That is why PalDock combines cookie and cookieless tracking to deliver the highest level of accuracy. Every conversion is counted, even when the process takes longer. Optimize Optimize your Paid Ads Running Paid Ads for your site? Wondering which exact clicks lead to conversions on the advertiser’s end? With our custom tracking, you can tag each click from your ads (using tools like Google Tag Manager) and attach it to your affiliate links. So when a sale or conversion occurs, you’ll pinpoint which exact click made it happen. Allowing you to automatically optimize your ads because PalDock can directly send this data to your Ad system via a server-to-server postback.  Aggregate Aggregate Product Data Comparison is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds including your own for easy comparison on your sites. The best part? Updates sync automatically with advertiser XML changes, but you also have the flexibility to tweak things manually.  Nothing compares. Upgrade your stack. Power your affiliate & lead genwith one smart platform. Request a demo Start for free Generate Generate banner from feeds Easily create banners from your Product Data Feed. Whether you need banners for specific products, categories, or any other criteria, our system ensures they’re always updated with the latest product information or highlights the top product in its category. Say goodbye to manual updates; enjoy seamless and automatic banner generation. Build Build your own product Sending clicks to advertisers is decent, but let’s face it, it’s like throwing darts in the dark. You can’t really steer the conversion once it’s on their website. Here’s where Lead Generation shines. Instead of just routing clicks with unpredictable outcomes, why not gather leads and orders directly on your site and pass on this valuable data? It’s a win-win-win! Your visitors get extra value, you grow a robust database, and essentially, you’re crafting your very own product and the Advertiser is happy for a hot lead. The result? A significant revenue increase, as a solid lead far outvalues a mere redirect. Plus you get an edge over your competitors with your own product. 15+ Years of Affiliate& Leadgen Expertise Our founder’s experience as Affiliate Partner, Advertiser, and Network shaped Paldock into the ultimate all-in-one platform. Case Studies Breakdowns of real projects Our case studies go deep. What worked, what didn’t, and why. We break down every step – no fluff, no shortcuts. Browse Case Studies → Case Study Case study: How Lender Orka Ventures Scaled Affiliate Operations Orka Ventures, an online lending group that wanted to scale fast across countries and onboard affiliates quickly. But their custom, API only setup was hard to integrate, blocked fast onboarding and did not support proper link tracking or attribution. They needed something better. Read more: Case study: How Lender Orka Ventures Scaled Affiliate Operations Case Study Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Leadgenia, a European affiliate network, wanted to scale its network with lead generation. But their previous provider, TUNE, was too expensive and limited. They needed something better. Read more: Case Study: How Leadgenia Turned Lead Generation into a New Revenue Stream Case Study Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Dostartu, a European virtual office broker, wanted to launch a scalable comparison and lead generation project in a niche where authorities treat “good” and “bad” company addresses very differently. But building everything in-house would have been slow, expensive and hard for partners to integrate. They needed something better. Read more: Case Study: How Dostartu Launched a Plug-and-Play Comparison with Affiliate Program and No Developer Case Study Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Silverside, a European online lender, wanted to scale its loan volumes with affiliate lead generation. But their custom in house tool was holding them back, was hard for partners to integrate and did not let them fully benefit from this growing channel. They needed something better. Read more: Case study: How Lender Silverside Multiplied Loan Volume with Lead Generation Evaluate Reporting The best part is that PalDock lets you track both clicks and lead performance seamlessly in one place. No more juggling two tools or wasting time on custom setups. All parties get access to a real time dashboard where they can see and verify data, which brings full transparency and eliminates the need for sending Excel files back and forth. Start your own Affiliate program Thinking big? Considering running your own affiliate program in the future? Dive into recruiting partners, customize commission rates or tiers, and explore many more possibilities. Set your sights on scaling up with the right tools in hand. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. If there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! Request a demo Start for free Built for every player in the affiliate game. Whether you’re an affiliate, a broker, a program owner, or running an entire network, PalDock is built for you. Affiliate Partner Affiliate Program Affiliate Network Affiliate Partner PalDock helps you launch and scale affiliate revenue fast, with no developers, no setup fees, and no hidden limits. Centralize Your Conversion Insights Consolidate results from advertisers and networks into one dashboard. One login, one platform. If they use PalDock too, you can generate assets and send invoices without switching accounts. Manage & shorten links at scale Handle all your links in one place. Auto-update them across your sites, monitor link health, and use lightning-fast branded short links that convert better. Grow beyond just clicks Don’t just send traffic – capture leads, compare product feeds, build forms, and even scale into your own affiliate program or sub-network when you’re ready. Try for Free → See all features Affiliate Program PalDock gives you everything you need to launch and run a high-performing affiliate program, with full control over offers, tracking, approvals, and payouts, without custom development or fragile integrations. Manage Your Affiliate Partners Recruit, onboard, and manage partners in one place. Categorize and tag them, assign affiliate managers, and set up any commission model, including CPA, CPS, revenue share, or custom formulas. Motivate partners with bonuses. Track Affiliates and Conversions Track affiliate traffic in one place. Set attribution rules to prevent double payouts and prioritize paid campaigns when needed. Attribute conversions via cookies, cookieless tracking, or promo codes, and view everything in one unified dashboard. Always-Up-To-Date Marketing Assets Control marketing assets with expiration dates and automatic fallbacks, so affiliate sites never show outdated banners. Affiliates can use auto-updating HTML banners or real-time product feeds, ideal for comparison sites. Try for Free → See all features Affiliate Network PalDock provides everything you need to build and operate an affiliate network, connect advertisers and partners, automate tracking and payouts, and scale operations, all without platform lock-in or heavy engineering. Boost Your SEO with Affiliate Traffic Turn your own site into an SEO redirect hub. Use a 301 from affiliates to your domain, then a 302 to advertisers to retain SEO value. Add remarketing pixels to capture and retarget affiliate traffic for more revenue. Invoicing Made Simple Receive affiliate invoices or auto-generate them, with accurate balance adjustments. Create advertiser invoices, track payment status, and approve commissions once advertisers pay. Build Own Products and Get an Edge Build unique products by leveraging Advertiser offerings, adding value for both affiliate partners and end-users alike. Promote it to affiliates through links or API for Lead generation. Try for Free → See all features #### Refersion Alternative What is Refersion? Refersion is a well-known affiliate tool in the e-commerce space, especially among Shopify and BigCommerce merchants. It integrates smoothly with major storefronts, offers coupon tracking and gives store owners an easy way to launch an affiliate program without custom development. That convenience explains its popularity with small to mid-sized brands. The limitations appear once businesses want to do more than just basic affiliate tracking. Refersion has limited flexibility in commission logic, reporting is elementary and larger brands often complain about slow performance and the lack of enterprise features. Pricing is also considered high compared to what the tool actually delivers, with extra costs for add-ons that still don’t cover advanced workflows. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Refersion vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: RefersionPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Report a bug URL: https://paldock.com/report-bug/ #### Request demo See Our Product in Action Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry No setup fee No credit card required Cancel anytime Try for Free → Get in touch → #### Rewardful Alternative What is Rewardful? Rewardful is a lightweight referral and affiliate tool built specifically for Stripe users. Its biggest advantage is simplicity: you can connect it to your Stripe account in minutes and start offering affiliates recurring commissions on SaaS subscriptions. For early-stage startups this is attractive because it requires very little setup. The trade-off is functionality. Rewardful only does the bare minimum: link tracking, coupon tracking and payouts through Stripe. There is not anything more. No flexible commission formulas and almost no analytics beyond basic referral stats. Many users also point out that pricing is steep for what you get, since even the higher tiers still only cover the basics. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Rewardful vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: RewardfulPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Roadmap URL: https://paldock.com/roadmap/ #### Scaleo Alternative What is Scaleo? Scaleo is a newer affiliate tracking platform that positions itself as a modern alternative to legacy tools like HasOffers or CAKE. It has a clean interface, supports postback tracking, offers anti-fraud modules and markets itself heavily toward networks. On the surface it looks slick, but once you dig in, the limitations become clear. Scaleo is still primarily a click and conversion tracker. There is no native lead management, no embedded forms, no structured validation of data and no advanced lead handling. Commission flexibility is limited and invoicing or financial features are absent. Users also report that while the UI is fresh, workflows are shallow and documentation is thin, which makes more complex setups harder to manage. For affiliate networks that only need standard link and conversion tracking wrapped in a newer design, Scaleo can be appealing. For operators that expect a complete affiliate and lead-gen backbone with validation, cookieless tracking, multiple lead structures, embedded forms and API integrations, Scaleo falls short where PalDock was built to excel. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Scaleo vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: ScaleoPalDockTracks affiliate linksLead capture via embedded formsLead capture via embedded APIUnified dashboard for link, form and API conversionsAdvanced lead handlingGDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Schedule a call Let’s Talk About Your Project Let’s talk about your project. What problems are you trying to solve and which blockers have you identified? Discuss them with us. We will gladly help, and if PalDock is the right fit, we’ll get you started. #### Service comparison Affiliate Software Service comparison Affiliate Software Scale with a tool for all stages of Affiliates, Advertisers and Networks. No matter the industry No setup fee No credit card required Cancel anytime Try for Free → Get in touch → Intro If you’re a comparator website comparing any services and are interested in lead generation or affiliate marketing, it’s essential to have a tool that supports: Boost Clicks with the fastest URL shortener to create short branded links Effortless Link Management Bring your revenues back with Cookie-less tracking Optimize your Paid Ads thanks to Click tracking Track accurately affiliate or any other traffic and conversions For a more refined and effective affiliate marketing strategy, consider offering advanced features for your affiliates, such as: Centralize Your Conversion Insights Automate Product Data with Advanced Aggregation Boost Your Earnings with Lead Generation and build your own product Scale your business and start your own Affiliate program Check how PalDock can address these challenges and propel your revenues to new heights. Boost Clicks with the fastest URL shortener to create short branded links Lengthy, messy links can seriously harm your click-through rates. People either hesitate to click on them or get stuck in slow redirects. Paldock’s here to change the game. Turn those lengthy URLs into neat, branded links that represent your website with grace. With a direct connection to both your site and advertisers, we ensure super-fast redirects, beating any other URL-shortening tools. And the icing on the cake? Change a shortened link once, and it updates across multiple sites. No tedious, site-by-site changes. A real time-saver! Effortless Link Management Juggling multiple affiliate links or websites? Things can get tangled fast. That’s where Paldock steps in. Centralize and manage all your affiliate links from a single hub, eliminating the hassle of going through countless posts or sites to make link updates. But we don’t stop there. We actively monitor link health, ensuring users are smoothly redirected to an alternative you’ve set up if a link breaks. And, of course, we’ll promptly notify you.  Bring your revenues back with Cookie-less tracking Did you know? Up to 64 percent of global consumers agree that they accept all cookie permissions when prompted but rates vary by region according to YouGov’s global consumer study. If your advertiser relies solely on cookies, that’s a whopping 40% of potential revenues slipping away from you. But Paldock has a solution. With our Postback tracking, we bypass cookies altogether, ensuring every conversion and every cent is captured. PalDock ensures every possible dollar lands in your pocket. Optimize your Paid Ads thanks to Click tracking Running Paid Ads for your site? Wondering which exact clicks lead to conversions on the advertiser’s end? With our custom tracking, you can tag each click from your ads (using tools like Google Tag Manager) and attach it to your affiliate links. So when a sale or conversion occurs, you’ll pinpoint which exact click made it happen. Allowing you to automatically optimize your ads because Paldock can directly send this data to your Ad system via a server-to-server postback.  Track accurately affiliate or any other traffic and conversions Track traffic from your affiliates and any of your campaigns seamlessly. Set clear attribution rules to avoid double-paying for a single conversion. Prefer your paid campaign to take precedence over affiliate sources? We’ve got you covered. Use either cookie-based, cookie-less tracking or promo codes for transparent and fair conversion attribution. View all your traffic and campaign data, not just affiliate insights, in a unified dashboard. Centralize Your Conversion Insights Drowning in data from a multitude of advertisers and networks? Bouncing between systems to keep tabs on conversions can be overwhelming. Paldock simplifies it all. We bring together results from every corner into a unified dashboard. Just one login, one platform, and you have it all at your fingertips. And if your advertisers use Paldock as well? Even better! Generate promotional content or send out invoices directly, no need to toggle between accounts. Automate Product Data with Advanced Aggregation Product comparison is only as good as the freshness of your data. Whether you’re using dynamic banners or product XML feeds, keeping everything current is key, especially when managing multiple websites. Paldock makes it a breeze. Our platform offers self-updating HTML banners tailored for specific products, categories, or other formats, and the ability to pull together data from various XML feeds including your own for easy comparison on your sites. The best part? Updates sync automatically with advertiser XML changes, but you also have the flexibility to tweak things manually.  Boost Your Earnings with Lead Generation and build your own product Sending clicks to advertisers is decent, but let’s face it, it’s like throwing darts in the dark. You can’t really steer the conversion once it’s on their website. Here’s where Lead Generation shines. Instead of just routing clicks with unpredictable outcomes, why not gather leads directly on your site and pass on this valuable data? It’s a win-win-win! Your visitors get extra value, you grow a robust database, and essentially, you’re crafting your very own product and the Advertiser is happy for a hot lead. Think about it: If you’re promoting services, you can collect user info and match them with the perfect offer. The result? A significant revenue increase, as a solid lead far outvalues a mere redirect. Plus you get an edge over your competitors with your own product. Scale your business and start your own Affiliate program Thinking big? Considering running your own affiliate program or even an entire network in the future? It’s crucial to pick a platform that not only offers the features we’ve covered before but also empowers you to oversee your very own affiliates. Dive into recruiting, customize commission rates or tiers, and explore many more possibilities. Set your sights on scaling up with the right tools in hand so you don’t have to difficultly change them later. Looking for More? There’s only so much we can squeeze in here. If you feel something’s left out, take a peek at Paldock or drop us a line. Just remember, we’re truly dedicated to catering to every phase of Affiliate marketing for Advertisers. So if there’s a feature you’re after and we don’t have it yet, rest assured, we’ll get on it for you! PalDock Has Your Back! Whether you’re a publisher, affiliate, webmaster, influencer, advertiser or network, PalDock helps you grow your business. With cutting-edge tools and innovative solutions, we ensure you’re ahead of the competition. Try for Free #### Solid Affiliate Alternative What is Solid Affiliate? Solid Affiliate is a WordPress plugin positioned as a modern alternative to older tools like WP Affiliate Manager, but in practice it is still tied to the same ecosystem limits. It integrates well with WooCommerce and handles basic affiliate tracking reliably, yet its flexibility ends there. The platform depends on WordPress performance, has minimal automation options and lacks deeper analytics or partner management features. For small online stores it can be a convenient entry-level solution, but for scaling or cross-channel affiliate operations it quickly becomes insufficient. al One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → Solid Affiliate vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: Solid Affiliate PalDock Tracks affiliate links Lead generation Lead distribution Advanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### UpPromote Alternative What is UpPromote? UpPromote is a Shopify-focused affiliate app that has gained traction because of its tight integration with the Shopify ecosystem. For small and mid-sized e-commerce stores it is appealing: setup is simple, the app lives inside Shopify, and merchants can get a referral program running quickly. But it is ultimately just that – a Shopify app. The feature set is narrow and revolves around coupon or link tracking. No advanced features and reporting and very limited flexibility in commissions. Reporting is basic, and scaling the program across multiple stores or channels quickly becomes difficult. Many users also point out that pricing adds up fast relative to the limited functionality. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → UpPromote vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: UpPromote PalDock Tracks affiliate links Lead capture via embedded forms Lead capture via embedded API Unified dashboard for link, form and API conversions Advanced lead handling GDPR compliant The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → #### Wp Affiliate Manager Alternative What is WP Affiliate Manager? WP Affiliate Manager is a lightweight WordPress plugin that adds basic affiliate tracking to a site, but it feels more like a workaround than a real platform. It handles simple link tracking and commission recording, yet the functionality is minimal and reliability depends heavily on the hosting setup. Integrations are limited, the interface is dated and scaling beyond a handful of affiliates quickly becomes messy. For small blogs or one-off campaigns it can be acceptable, but for any long-term or professional affiliate program it is far too limited. One platform. All the tools. From tracking to payouts – Paldock replaces the mess. Start for free → WP Affiliate Manager vs PalDock We spent hundreds of hours researching our competitors. Instead of guessing, we built a full step-by-step guide on How to choose the right affiliate software. We used it ourselves to analyze dozens of different tools, mapping over 30 features and limitations along the way. We didn’t stop at the surface. We actually integrated them and went through their onboarding like real users. These are the key differences: WP Affiliate Manager PalDock Tracks affiliate links Lead generation Lead distribution Advanced lead handling The Affiliate Platform Guide Everything you need to choose the right affiliate platform in one place. Download the complete guide and keep it as your handy reference. Download ebook → ### KB Articles #### About commissions ⚠️ A commission is simply a rule that defines when and how a transaction should be created from a conversion. Conversions are performance metrics on their own. They carry no money. A commission is the rule that turns a conversion into a transaction with a payout and a result. Every commission exists twice: once for your workspace, meaning what you receive from the advertiser, and once for your partners, meaning what you pay them. The two are linked, so both transactions are always created together. What you can control When a transaction is created, using conditions such as offer, advertiser, conversion type, source, and channel. How much it is worth, as a fixed value, a percentage, or a calculation using system fields and values from tracking. What type of transaction it is, and what result it gets when it is created. How duplicates and repeats are handled, using recurrence limits and deduplication on the advertiser’s external ID. Who it applies to, using commission groups. Start here Commission conditions to create Transactions sets which conversions a commission applies to. Commission amount sets what the transaction is worth. Commission status controls whether a commission applies at all. When several commissions apply How PalDock picks a commission explains which commission runs and how many of them run. Multiple Commissions for the Same Conversion Type Commission order Commission ID lets the advertiser name the exact commission in a tracking request. Controlling the transaction Transaction type Auto-approve transactions Auto-set transaction result Avoiding duplicates Recurrence type limits how many times one commission can be applied to the same conversion. Deduplication based on advertiser’s ID keeps one transaction per external ID. Organizing and presenting Commission group targets commissions at selected affiliates. An affiliate can belong to only one group. Commission schedule changes amounts over time. Display amount shows a clean label instead of a formula. Commission detail adds a short note to the commission table. PalDock calculates reporting metrics such as ROI from the difference between your amount and the partner payout. See Performance reports. #### About connection creator Connection Creator is a visual builder. You place nodes on a canvas and connect them with arrows. Together they form a scenario = a flow that runs whenever something happens in PalDock. Nodes and connections Node = one action. Send an HTTP request, set a variable, modify a field, wait, finish. Connection = an arrow between two nodes. It decides what runs next. Arrows can carry conditions. Scenario and run Scenario is the flow you build and save. Run is one execution of it. Every lead, postback or form submit starts its own run. Runs are logged separately, so you can always see what happened to one specific lead. Types of scenarios A scenario always belongs to one context. The context decides what triggers it and what data it receives. Integration: sends a lead to an advertiser and processes the answer. Structure: validation: checks a value while the form is being filled in, and can block the submit. modification: fills a field with a value from an external service (Autofill). autocomplete: suggests values to the visitor while typing. Tracking: S2S postback (incoming): processes a conversion or status update sent to PalDock. Tracking API (outgoing): sends conversion and status data from PalDock to affiliates or other systems, and can also poll an advertiser for a result. Feed: pulls product or offer data from an external source. How data moves The first node receives the incoming data – such as form fields, tracking parameters, system tags and others. Each node then reads that data, does its job, and writes its own values back. Everything travels forward. A node can use any value produced by any node before it. Nothing is passed backwards. Order Nodes run one after another, following the arrows. If a node has several outgoing arrows, every arrow whose condition is met is followed. Arrows are evaluated in the order they are listed on the node, so if two of them can both apply, the one higher in the list runs first. If a condition is not met, that arrow is skipped. A branch can end on its own without stopping the other branches. Immediate or background Some scenarios must return an answer while the visitor is waiting such as form validation, autocomplete or a lead sent over the API. These run immediately and the caller waits for the result. Others run in the background such as outgoing Tracking API. They are queued and processed without blocking anything. Pausing A Wait node pauses the run for a set time. A Webhook node pauses it until an external system calls back. The run stays open, keeps its data, and continues from the same place. Errors and limits A node runs once, with no automatic retry. Every part of the flow also has a time limit, and a scenario that runs while a visitor waits has the tightest one of all. See Limits and timeouts. Failures are counted and written to the run log. Use response conditions to decide what should happen next instead of relying on the failure itself. A Breaker node limits how many times a loop may repeat, so a flow can never run forever. A scenario can start another scenario, but a scenario cannot call itself in a circle. Where to look when something breaks Every run stores the input and output of each node. Open the run and follow it node by node and you will see the exact data each node received and returned. #### About Offers Offers are the core element in PalDock where affiliates send traffic. Each offer represents a campaign or product that can be promoted, tracked, and monetized. Every offer has a status: Active – the offer is visible and can be promoted by affiliates. Inactive – the offer is hidden and cannot be used until reactivated. It also has an access level, which decides which partners can see it and whether they need approval to promote it. Within an offer, you can configure the most important settings, including: Tracking links – the URLs used by affiliates to drive traffic. Forms & APIs – the entry points where leads are submitted, either through an iframe form or directly via API. What they collect is defined by the offer’s structures, and an offer can have more than one. Payouts & Commissions – rules for how affiliates are rewarded for approved conversions (clicks, leads, prospects or sales). Filters – conditions that determine whether traffic should be accepted or rejected (e.g., based on data, values, history, or caps). Capping – limits on the number of clicks, leads, prospects or sales an offer will accept. Offers can also include advanced features such as lead distribution (pingtree) and affiliate-specific settings (e.g., custom payouts or exclusions from certain features). In short, Offers define what affiliates can promote, how the traffic is processed, and under what conditions affiliates are rewarded. #### About Reports and Logs Reports and Logs is where you find out what happened. The difference between the two is the level you are working at. Reports aggregate. A row is a day, an affiliate, an offer, a channel. They answer how many and for how much. Logs are one row per event. A click, a lead, a conversion, a request. They answer why this particular one did what it did. Most questions start in a report and end in a log. The reports Performance: results over time, and the same data grouped by affiliate, advertiser, or offer. This is where you look at profit, costs, revenues, and the per lead and per click metrics. Pingtree: how leads moved through distribution, per offer and per channel. Pings, verifications, posts, and what each channel paid. Transactions: every transaction as its own row, both sides of it, with the identifiers and the detail behind each one. The logs Clicks and leads: what arrived, whether it was accepted, and what happened to it afterwards. Conversions: every conversion PalDock holds and whether it produced a transaction. This is where you go when a conversion exists but no payout came out of it. Integration requests: each run of an integration, node by node, with what was sent and what came back. Tracking requests: every pixel, postback, and Tracking API call, and how each was handled. All of them are described in Logs. What every table shares Reports and logs are the same kind of table, so the same tools apply to all of them. Period and granularity: a date picker with the usual presets, and a choice of hours, days, weeks, or months. Highlights: the key numbers above the table, and the lines in the chart. Rows can be plotted instead. See Show rows in chart. Advanced columns: which columns are on screen, from a fixed set of groups. Filters: including filtering by columns you are not displaying. Result type filter: whether pending and rejected transactions are counted. Reporting time basis: which of the three dates a transaction is reported on. Export and Import. The last two are worth knowing before you compare numbers with anybody. Two people looking at the same data on a different time basis or a different result filter will get different totals, and both are correct. Who sees what Affiliates and advertisers open the same reports you do, restricted to their own data. Columns that belong to the other side are hidden or relabelled, and an affiliate is never shown which channel bought a lead. See Transactions report. Individual report functions can also be limited by role, from adding a Highlight to exporting. Where to start Which affiliate is performing best: performance report, grouped by affiliate. Why leads are not selling: pingtree report, then the lead log. Why this lead was rejected: lead log, read the status, then the detail. Why there is no payout for this conversion: conversion log, then How PalDock picks a commission. Why the advertiser’s postback did nothing: tracking log, then Tracking errors and reasons. #### About settings Settings is where you configure the workspace itself: how it looks, what it allows, how it measures, and who can get into it. It is not the same thing as your personal account. Your name, email, password and billing details belong to your PalDock account and follow you into every workspace you have access to. See One Account, Multiple Workspaces. Settings is divided into six areas: General covers branding, defaults for new partners and advertisers, what the workspace permits, and minimum payouts. Users is who has access and what they are allowed to do. Tracking covers domains, conversion types, the cookie window, lead uniqueness and what is excluded from measurement. Labels are the tags and categories you use to organise things across the workspace. Fields are the fields available to every structure in the workspace. Billing and documents is invoicing and the paperwork behind it. Everything here applies to one workspace. If you run several, each has its own settings. General Customization How the workspace presents itself to partners and advertisers. Name is what people see. Slug is the short form used in URLs. Workspace domain is the address the portal runs on. Logo, dark mode logo and favicon. Upload the dark version too, otherwise a light logo disappears against a dark background. Workspace template sets the default look and the terminology for your vertical, such as lending. Default settings Values applied to everything created in the workspace unless something overrides them. Default country and default currency are what a new offer, partner or advertiser starts with. Affiliate billing decides whether billing follows the workspace settings or is handled per partner. New partners and new advertisers decide what happens when somebody registers: approve them automatically, or hold them for manual approval. Automatic is convenient and means anyone who finds your registration form is in. Show my affiliate program in the catalog lists your program publicly so affiliates can approach you. Leave it off if you only work with partners you recruit yourself. Categories decide where your program appears in that catalog. Options What the workspace permits. These are the settings that change what other people can do, so they are worth going through deliberately rather than leaving at their defaults. Allowed sources limits how leads may reach you: a link, an iframe, or the API. Turning one off closes that route for everyone in the workspace. Allowed form edits decides how far a partner may customise an embedded form. Colours and texts are the usual choices. The more you allow, the further a form can drift from what you designed. Lead sharing with partners decides whether partners can see lead data, rather than only counts and payouts. Custom pingtrees decides whether partners may build their own distribution rather than using yours. Custom tokens decides whether partners may define their own parameters. Lead anonymisation removes personal data from leads after a set time, counted from when the lead arrived. The default of 86 400 seconds is one day. This is the setting people reach for when a retention rule requires it, so check what your obligations actually are before changing it, in either direction. Minimum payouts The smallest amount a partner has to reach before they can be paid, set per currency. Set one for every currency you actually pay in. A partner earning in a currency with no minimum has nothing to reach, which is rarely what anyone intended. #### About structures Structures define the format of data collected and processed in PalDock. They describe which fields are included, how those fields behave, and how the data is used across forms, APIs, feeds, and integrations. By using structures, you ensure that all data in PalDock is consistent and reusable. Types of Structures Form Structure – defines the fields collected when a lead is created. Used in forms, APIs, and partner integrations. User Structure – defines the fields collected when users register or manage their account. Separate structures exist for Affiliate partners and Advertisers. Feed Structure – defines the format of product feeds (e.g. product name, price, availability) imported into PalDock and used in affiliate display or lead distribution. Fields in Structures Each structure is made of fields. Fields determine what kind of data is collected (e.g. text, number, email). To keep structures consistent and avoid duplication, PalDock supports three levels of fields: Global fields – predefined system fields used across all workspaces (e.g. First Name, Email). Local fields – workspace-wide fields created by admins, reusable across multiple structures. Custom fields – fields created directly inside one structure, specific to that structure. 👉 We recommend using global fields whenever possible, and local or custom fields only when necessary. How structures are used A structure on its own collects nothing. It becomes active when something is attached to it: A form structure is attached to an offer, and an offer can have more than one. That is how two landing pages that differ by a single field share one offer. See Multiple Structures for Offers and Integrations. An integration is built on exactly one structure. The fields in that structure are what you map into the advertiser’s request. A user structure is used by the registration and account forms for affiliate partners and advertisers, so it is not attached to anything. The same structure serves the form, the embeddable form and the API. A field added to the structure appears in all three, and in the API documentation your partners see. Advanced Options All structures can use the same advanced features: Field settings – define labels, placeholders, default values, and visibility rules. Validation – enforce correct data formats or check values against external services. Modify – fill or transform a field value, either from another field or from an external service. AutoComplete – suggest values to the user while they are typing. Translations – localize field labels and placeholders into multiple languages. ⚠️ Validation, Modify and AutoComplete are powerful features, but because they can rely on external services, a misconfiguration can break the entire system, preventing the form from being submitted and the lead from being created. #### About Tracking Tracking is how conversions get into PalDock. It records clicks, leads, prospects, sales, and any custom type you define, and it decides what data those records carry. Turning them into payouts is a separate step, handled by commissions. The tracking methods Pixel: browser based, fired on the advertiser’s confirmation page. Easy to deploy, but depends on cookies and can be blocked. S2S postback: server to server, sent by the advertiser’s system. Reliable and cookie free. Tracking API: PalDock asks the advertiser’s system about a conversion, or forwards results out to an affiliate. Manual import: upload conversions yourself when no automated method is available. Most setups combine at least two, typically a pixel and a postback, so a blocked pixel does not cost you the conversion. When the advertiser sends their own external ID, PalDock recognises the repeats and keeps a single conversion. Start here Conversion IDs explained: which identifier to send and when. Read this before you brief an advertiser. Tracking processing: what happens to a request after it arrives. Conversion type: which types exist, which channel can create which type, and how to add your own. Tracking parameters: the full parameter reference. A step by step setup guide for a specific offer is in the Offer editor, Tracking tab. Setting up each method How to set up pixel tracking Update pixel, for adding URL and cookie data to a conversion that already exists Tracking S2S Postback Tracking API Manual Tracking and Transaction Import Attribution and duplicates Tracking by vouchers: a discount code assigns the conversion to the affiliate who owns the code. Click deduplication: repeated clicks from the same visitor count once. Deduplication based on advertiser’s ID: the same order reported twice counts once. Sending results out Affiliate postback: affiliates forward their own results into their systems. When something does not work Tracking and Conversion Logs: see the raw requests and the conversions they produced. Tracking errors and reasons: what each outcome and status means, and what to do about it. A conversion that is recorded correctly still does not have to produce a payout. That depends on the commission. See How PalDock picks a commission. #### About User management User Management is where you decide who is in your workspace and what they are allowed to do. There are three kinds of people in it. Affiliates: the partners who promote your offers and get paid for the traffic they bring. Advertisers: the companies whose offers you run and who pay you for the results. Admins: your own team, with permissions deciding how much of the workspace each of them sees. One account, many workspaces Nobody registers twice in PalDock. A person or a company has one account, and that account connects to as many workspaces as they work with. See One Account, Multiple Workspaces. That splits their data in two: Global fields belong to the account. Email, nickname, billing details. They follow the user everywhere, and only the user can change them. A change propagates to every workspace they are in. Custom fields belong to your workspace. You define them, you can edit them, and nobody else sees them. For a partner who already has a PalDock account, joining you is one click and the global fields are already filled in. The only thing left is whatever custom fields you ask for, which is a good reason to ask for few. See Local, Global and Custom fields. How people get in Three routes, for affiliates and advertisers alike: They register themselves through your registration form. What that form asks for is set by the user structure. You invite them by email. You add them manually. Email and nickname are enough. They fill in the rest when they log in. Whether a new registration is live immediately or waits for you is a workspace setting, along with whether your program is listed publicly in the catalog. See Settings. Admins are different. You create subaccounts for colleagues and assign them permissions, and they do not self-register. What each type can see Partners work inside the same interface you do, with their own data only. Affiliates see their offers, their traffic, and what they earn. What you pay them is labelled Revenue on their side. They are never shown which channel bought a lead. Advertisers see the offers they own and what they pay. What they pay is labelled Costs on their side, and they see nothing about your affiliates. Admins see what their permissions allow. An admin assigned to manage specific partners sees only the results of those partners. See Transactions report for how columns change per role, and Filters for what a partner can and cannot filter by. Organising accounts Whatever the type, an account can be categorised by country, language, category, and tags. Those are not decoration. They are filters and grouping dimensions in every report, which is what makes them worth setting when the account is created rather than later. Two settings do more than organise: Commission group on an affiliate decides which commissions apply to them. It is how you pay different partners differently for the same offer. Management assigns an admin to an affiliate or an advertiser. That admin then sees only the accounts they manage. Access can be suspended or removed without deleting anything. The account keeps existing in PalDock and in its other workspaces, it simply stops having access to yours. #### Admins Admins are your own team. Unlike affiliates and advertisers, they never register themselves. You create the subaccount and invite them. Adding an admin Enter a name, an email, and optionally a phone number, then assign permissions. The account can also be categorised by country and tags. Permissions Assign one or more: Affiliate Manager: manages affiliate partners only. Can create partners, manage them, and see their performance. Offer Manager: manages advertisers and offers only. Can create offers, manage them, and see their performance. Analyst: views statistics and exports them. No access to partners, offers, or advertisers as entities. Viewer: views entities only. No access to statistics. Billing: invoices and billing documents only, limited to the documents available to the parent account. They combine. Somebody who needs to run partners and read the numbers gets Affiliate Manager and Analyst, not a compromise between the two. Permissions and assignment together A permission says what kind of thing an admin can work with. Management says which specific ones. An Affiliate Manager sees the partners assigned to them, not every partner in the workspace. Assignment is done on the partner, in Affiliates and Advertisers. This is what lets two managers work in the same workspace without seeing each other’s accounts, and it is also the thing people forget: an Affiliate Manager with no partners assigned sees nothing, and it looks like broken permissions. What admins do not get The account owner’s data. Nickname, email, password, and billing details belong to the PalDock account and are changed only by its owner, whatever permissions you hold. See One Account, Multiple Workspaces. Everything in reports. Individual report functions can be limited by role, from adding a Highlight to exporting. An Analyst reads and exports, a Viewer does neither. Access can be suspended or removed at any time. The person keeps their PalDock account and any other workspace they belong to. #### Advanced columns Every table opens with a core set of columns. Advanced columns are everything else the table can show, from financial detail to the values a partner sent with the lead. Open the picker with the column icon in the table header, then switch individual columns on and off. Your selection stays with you, so a table you have set up once opens the same way next time. Column groups Fields are grouped, because the full list is long. The groups always appear in the same order, in the picker and in the table, so a column sits in the same place in every report. Performance: clicks, leads, transactions, revenues, costs, and the metrics derived from them. Finance: payouts, margins, invoice data, and payment statuses. Categorization: tags, categories, countries, languages, and other classification fields. Entities: identifiers and names for affiliates, advertisers, offers, and everything related to them. Processing: the technical side. Source type (link, iframe, API), statuses, processing times, error codes, and similar. Data: the custom fields collected by your forms. Performance metrics The performance columns are laid out in four blocks, separated visually so you can tell at a glance which unit a number is in. Totals The plain counts and amounts for the selected period. Clicks, Leads, Transactions Costs: what you pay your partners Revenues: what the advertisers pay you Profit: revenues minus costs Per lead CR: conversion rate from lead to transaction CPL: cost per lead EPL: earned per lead PPL: profit per lead Per click CR: conversion rate from click to transaction CPC: cost per click EPC: earned per click PPC: profit per click Per transaction ACV, average conversion value: revenue divided by the number of transactions. How much one conversion is worth. APV, average payout value: payout divided by the number of transactions. How much one conversion costs you. Per lead and per click answer how well traffic converts. Per transaction answers how valuable a single conversion is, which is a different question and often moves in the opposite direction. Columns in logs and the transactions report Row level tables carry columns that make no sense in an aggregated report: affs1 to affs10 and adv1 to adv10, the custom values passed with the click or the lead Device, user agent, and referrer Value and coupon Commission ID, the commission that created the transaction Product See Transactions report and Logs. Hidden columns still work A column does not have to be visible to be useful. You can filter by a column that is switched off. See Filters. You can export every available column, whether or not it is on screen. See Export. This is how you keep a table readable while still working with the full dataset. Filter by country without adding a country column, then export everything when you need the detail. For how each metric is calculated, see Columns explained. #### Advertiser Each offer must have a main advertiser assigned. This can later be used in conditions for: Tracking, especially for postbacks. Commissions. Additionally, the Advertiser reports allow you to view results grouped by advertiser. This is useful when one advertiser has multiple offers, since offer-level reports do not give a complete overview in such cases. Giving advertisers access You can invite advertisers into your workspace and give them different levels of access to the offers assigned to them. There are three permission levels: View – the advertiser can log in, see their assigned offers, and view reports and transactions, excluding information about affiliate partners. Edit – in addition to viewing, the advertiser can also edit the offer settings. Manage – full access to the offer, including editing, viewing all related data, and seeing affiliate partners. Ideal if the advertiser handles everything on their side, including approving affiliate requests. This way, you can choose whether advertisers only observe their performance, collaborate on setup, or manage everything themselves. The level applies per offer, so the same advertiser can manage one offer and only watch another. For inviting advertisers and managing their accounts, see Advertisers. #### Advertisers Advertisers are the companies whose offers you run and who pay you for the results. This is where you add them and organise them. What they pay is defined on the offer and its commissions, not here. Adding an advertiser Three routes into your workspace: They register themselves through your registration form. You invite them by email. You add them manually. Whether a new advertiser is active straight away or waits for your approval is set in Settings. Adding one manually Two fields are enough: Email Nickname Everything else the advertiser fills in when they first log in, and it appears in the advertiser detail from then on. If the email already belongs to a PalDock account, you are told so, and the email is the only thing you need. The rest of that company’s data already exists and comes with them. See One Account, Multiple Workspaces. Self-registration The registration form is yours to define, through the user structure. It can ask for two kinds of fields. Global fields belong to the PalDock account. Prefer these. For an advertiser who already has an account they are pre-filled, so signing up is close to instant. You cannot edit them, only the advertiser can, and their changes propagate to every workspace they are in. Custom fields belong to your workspace. You define them and you can edit them later in the advertiser detail. See Local, Global and Custom fields. Management Assign an admin to the advertiser. That admin sees the results of the advertisers they manage and nobody else’s. See Admins. Categorisation Advertisers can be classified by country, language, category, and tags. These are filters and grouping dimensions in every report. The advertiser report groups by advertiser, so tags are what let you compare a whole set of them, for example every advertiser in one vertical, without picking them out by hand. What the advertiser sees An advertiser logs into the same interface you do, restricted to their own data. The offers they own, the results on those offers, and their transactions. What they pay you is labelled Costs on their side. They see nothing about your affiliates. Which partner produced a lead is yours, not theirs. The access an advertiser has to an offer is set on the offer itself. See Advertiser. #### Affiliate ID rewrite You can override the affiliate a lead is attributed to by passing the parameter owner_id: in the URL of the affiliate link, or in the URL of the page containing the embedded form. Example: www.example.com?owner_id=12345 Affiliate link use case This is useful when you want to place an offer link on your final landing page and attribute the resulting conversion to the affiliate delivering the traffic. Embedded form use case This is useful when you generate traffic on your own website but want to attribute certain traffic sources to a separate affiliate account. By appending owner_id to the URL, those leads are tracked under the specified affiliate. It decides who gets paid The affiliate on a lead is the affiliate you pay for it, so this parameter moves money rather than just labelling a report. Use it where you control the page it sits on, and remember that anyone who can edit that URL can change the attribution. #### Affiliate link Users with access to a specific Offer can view its details together with allowed propagation options (Link, iFrame, API). Affiliate links can carry multiple tracking parameters, all of which are stored in the system and available for reporting and optimization. Each click generates a unique click ID, ensuring that every action can be tracked accurately. The redirection process itself is optimized for speed and reliability, so customers experience minimal delay when clicking a link. Link Parameters The most common parameters are: pcid – the identifier PalDock assigns to every click. Always present unless you rename it, see below. affcid – a custom click identifier provided by the affiliate. affs1 to affs10 – custom fields where affiliates can pass their own IDs or values for tracking and reporting. destination – a URL pointing to another page within the same advertiser domain instead of the default landing page. This allows affiliates to send traffic directly to a specific product or category page, for example an online shop linking users to a chosen product detail. The URL must be URL-encoded, for example destination=https%3A%2F%2Fwww.example.com%2Fproduct%2F123. See Deep link. For the full list, see Tracking parameters. pcid is the Origin ID pcid is the parameter name. The value it carries is the Origin ID, which is what identifies a click everywhere else in PalDock: in postbacks, in the Tracking API, in logs and in reports. One value, two names, depending on where you meet it. In a URL it is pcid. In everything that talks about it afterwards it is the Origin ID. See Conversion IDs explained. pcid is generated automatically, but you can rename it to anything using ?anything={pcid}. Once {pcid} is used in a differently named parameter, the default pcid parameter is not added. Only your custom parameter containing the value remains. This is for advertisers whose systems expect the identifier under a name of their own, for example ?clickid={pcid} or ?subid={pcid}. Domains and URLs Redirects can run over different domains, giving flexibility in how links are displayed: PalDock domain – default option. (e.g., go.paldk.com/) Custom top-level domain (e.g., www.example.com/). Subdomain (e.g., go.example.com/). Folder redirect (e.g., www.example.com/out/). While this method is slower, it can be useful in email campaigns, allowing the sender domain and the button URL to match, which helps improve deliverability. Redirect Chaining Redirects can sometimes chain together, for example: A shortened link (e.g., example.com/go/offer) An affiliate link with parameters (e.g., go.paldk.com/offer=1&affiliate=1) A tracking link that points to the advertiser (e.g., www.advertiser.com/?source=paldock&id=1) When all of these are handled through PalDock, the system automatically optimizes the path by skipping redundant steps and sending the user directly to the final destination. Remarketing and Scripts Admins can enhance redirects by injecting scripts during the redirect flow via Server-side Google Tag Manager. While this may slightly slow down the redirect, it can be well worth it when combined with lead collection. This setup enables advanced remarketing scenarios based on user behavior with the redirects. For example, sending a follow-up email when a customer (known from lead) clicks through a specific link or activating targeted ad campaigns for users who interacted with certain offers. #### Affiliate postback Affiliates can forward their own conversion data into any external system. In PalDock this is a Tracking API that the affiliate creates and manages in the Affiliate Postback section. Typical uses: Sending conversions into your own tracker or reporting tool. Passing conversions on to an upstream network. Firing conversions into ad platforms so campaigns can optimise on them. What an affiliate can set The URL the data is sent to, and the parameters that go with it. See Tracking parameters. Conditions, so only some conversions are sent, most often a condition on offer or on result. A trigger, deciding whether it fires when a transaction is created, when it is updated, or both. Two things worth knowing You normally receive two requests per conversion, one when it is created with a pending result, and one when the advertiser decides it. Filter on result if you only want the final one. Several commissions mean several requests. Each transaction is sent separately, so aggregate them on your side. What you cannot see Postbacks an admin created are not listed here, even when they are limited to your account. You only see the ones you created yourself. Full detail on conditions, triggers, retries, and timeouts is on the Tracking API page. #### Affiliates Affiliates are the partners who promote your offers and get paid for what they bring. This is where you add them, organise them, and decide what they are paid. Adding an affiliate Three routes into your workspace: They register themselves through your registration form. You invite them by email. You add them manually. Whether a new partner is active straight away or waits for your approval is set in Settings. Adding one manually Two fields are enough: Email Nickname Everything else the partner fills in when they first log in, and it appears in the affiliate detail from then on. If the email already belongs to a PalDock account, you are told so, and the email is the only thing you need. The rest of that person’s data already exists and comes with them. See One Account, Multiple Workspaces. Self-registration The registration form is yours to define, through the user structure. It can ask for two kinds of fields. Global fields belong to the PalDock account. Prefer these. For a partner who already has an account they are pre-filled, so signing up is close to instant. You cannot edit them, only the affiliate can, and their changes propagate to every workspace they are in. Custom fields belong to your workspace. You define them and you can edit them later in the affiliate detail. Every custom field you add is one more thing standing between a partner and a finished registration, so ask for what you actually need. See Local, Global and Custom fields. Commission group The commission group decides which commissions apply to this affiliate. Use the default group, or create a new one in the Commissions section. This is how you pay two partners differently for the same offer, so it is worth setting when the account is created rather than after the first payout. Management Assign an admin to the affiliate. That admin sees the results of the partners they manage and nobody else’s. See Admins. Categorisation Affiliates can be classified by country, language, category, and tags. These are filters and grouping dimensions in every report, so consistent tagging is what later lets you compare a whole group of partners rather than picking them out one by one. What the affiliate sees An affiliate logs into the same interface you do, restricted to their own data. Their offers, their traffic, and their transactions. What you pay them is labelled Revenue on their side. They are never shown which channel bought a lead, through a column, a filter, or a grouping. Whether they can see lead data at all, rather than only counts and payouts, is a workspace setting. See Settings. #### Allowed Delivery method When creating an offer, you can choose how it can be promoted. There are three available methods: Link – redirects the visitor from one website to another. Embedded form – embeds a form on a website to generate leads directly there. API – connects any custom form on the backend to receive leads from it. You can freely decide which methods are available within an offer or across the entire workspace. Turning a method off for the whole workspace If you disable a method in Workspace Settings, all related features are hidden throughout the workspace: Tabs in offers. Click and lead metrics and their logs. If both Form and API are disabled, this also hides: Pingtrees and their reports. Structures and their logs. Integrations and their logs. Designs. This is about what you see, not about what exists. Nothing is deleted, and turning the method back on brings everything back as it was. Turning a method off for one offer In the Offer Editor, only the tabs relevant to the selected methods are displayed. Set this before partners start promoting. A method you disable later leaves links or embed codes already published on partners’ sites, and you need to know what happens to that traffic before you switch it off. #### API integration Users with access to a specific Offer can view its details together with allowed propagation options (Link, iFrame, API). For each Offer with API propagation enabled, PalDock automatically generates API documentation for affiliates (in Offer preview → API). The documentation is derived directly from the Form Structure where input fields are defined. This makes it possible to generate and maintain API specs automatically, so partners can both read and test the integration before development. PalDock uses a single endpoint for all requests and workspaces. The offer and the structure are given as query parameters, so you do not need different endpoints for different tenants or offers. With the Global Fields feature, the payload format stays almost the same across all offers, except when you add custom fields. This setup makes things much easier. Affiliates can run many Offers, even from different workspaces, using just one endpoint. There is no need to handle lots of different URLs and integrations. The PalDock API works the same way everywhere, so integrations are simple and consistent. Thanks to this, integrations are quick and affiliates can start sending their first leads on the very same day they are onboarded. The endpoint POST https://api.paldock.com/api/{tenant}/conversions/api?o={offer_id}&structure={structure_id} o – the offer the lead belongs to. structure – the form structure the payload follows. Both values, along with the affiliate’s API token, are in Offer preview → API, where the affiliate can also read the generated documentation and test a request before writing any code. Response codes 200 – the lead was created. See the response fields below. 202 – the lead was created and the detailed breakdown is included. See External Final Page. 403 – the API token is not valid. 404 – no pingtree was found for the given offer and structure. 406 – the lead was rejected. See Refuse leads. 422 – the payload or the query parameters did not validate. Process after Lead Submission When a lead is submitted, the response includes url. The affiliate’s frontend should send the customer there right away. That URL is the Internal Final Page, https://portal.paldock.com/{tenant}/processes/{process_id}. The page waits for the lead to finish processing and then shows the internal screens (verification, thank-you page, final page) or redirects onward, depending on how the Offer is configured. Depending on the Admin configuration, PalDock supports two response modes: Basic Response – status and URL only. { "process_id": "a1feecc3-dcaf-470b-9b54-f1bdbdeff9dc", "url": "https://portal.paldock.com/tenant/processes/a1feecc3-dcaf-470b-9b54-f1bdbdeff9dc", "origin_id": "1234", "status": "pending" } Detailed Response – full breakdown of how the lead was processed across pingtree channels. See External Final Page. Response fields process_id – identifies the lead in PalDock. Use it when you ask for the status later, and in the Internal Final Page URL. url – where to send the customer next. eid and origin_id – the tracking identifier for this lead. It is the same value the affiliate link carries as pcid. See Conversion IDs explained. status – pending, approved or rejected. Three older field names are still returned and mean exactly the same as their replacements: id for process_id, external_id for eid, and redirect_url for url. They are kept so existing integrations keep working and will be removed in a future version. Build new integrations on process_id, eid and url. API Parameters The most common parameters used in PalDock are: affcid – a custom click identifier provided by the affiliate. affs1 to affs10 – custom fields where affiliates can pass their own IDs or values for tracking and reporting. external_redirect_url – an alternative URL where the user should be sent after submission. Must be URL-encoded. The External Final Page feature must be enabled. external_redirect_url_results – whether that page receives the full breakdown or only the basic result. True by default. test – marks the lead as a test so it will not be processed as a standard lead. sync – holds the response until the lead has been evaluated. The Refuse leads feature must be enabled. See below. status_url – a URL PalDock calls when the lead status changes. See below. external_redirect_url can carry placeholders that PalDock fills in: {process_id}, {affiliate_id}, and {data_<field_name>} for any field in the structure. So https://yourdomain.com/result?pid={process_id} arrives at your page with the identifier already in it. Tracking Lead Status (Approved or Rejected) When an affiliate sends a lead into PalDock, they may want to know whether it was approved or rejected. PalDock provides three ways to find out. Enable the Refuse leads feature in Offer settings to use any of them. 1. Synchronous response, recommended If the affiliate includes sync=1, PalDock holds the response until the offer evaluation is complete, instead of answering straight away with pending. This can take several minutes, depending on the offer logic. Affiliates must configure a sufficiently long timeout on their side. Although simple, it is the most effective solution. 2. Automatic S2S postback Include status_url in the request. PalDock then calls that URL whenever the lead status changes, with the same payload as the standard response. Request: { "first_name": "John", "last_name": "Doe", "status_url": "https://affiliate.com/postback/lead-status" } Postback sent by PalDock: { "process_id": "9e886baa-6804-4dfe-baf9-a065b66d7f87", "status": "approved", "url": "https://portal.paldock.com/tenant/processes/9e886baa-6804-4dfe-baf9-a065b66d7f87" } No repeated polling, minimal delay, automatic updates. 3. Polling endpoint, not recommended The affiliate can repeatedly ask for the current state using the process_id from the initial response. GET https://api.paldock.com/api/{tenant}/processes/{process_id} The response has the same shape as the one above. ⚠️ This means calling the endpoint every few seconds until the status changes, which creates unnecessary load on both sides. We do not recommend it in production. API Features Data feeds – responses can include a feed_id to match against external data feeds, for example logos, names, or additional attributes. The response may also override certain fields from the data feed for a specific lead. This is useful in cases such as mortgages, where an individual customer might receive a dedicated interest rate. For full details, see Data feeds. #### Auto submit The form can be set to submit automatically by adding the parameter system_submit=true. However, if some fields are missing, the form’s validation will trigger an error and the user will be asked to complete the missing fields. (Feature Auto submit must be enabled). Use case Auto Submit is especially useful when monetizing a lead generation database. Since you already have all the required user information, the lead can be sent directly into the pingtree (e.g., after the user clicks a button in an email). Optional confirmation step If you want to add an additional confirmation from the user, you can create a dedicated internal page that the user visits before the form is submitted automatically. You might also want to check out the Pre-filling fields feature, which automatically prefills the form with values to have it ready to be auto-submitted. #### Auto-approve transactions ⚠️ This setting is only available for workspace commissions from advertisers, because partner commissions reflect those values. If you are certain that you want specific transactions to be approved automatically, you can enable this in the advertiser commission detail under the Settings section “Auto-approve transactions.” When enabled, any pending transactions that meet the commission’s conditions will be automatically marked as Approved without manual review. Affiliates will see these commissions as approved, and depending on your payout settings, they may become eligible for immediate payout. In the commission list, those commissions will be marked with a ⚡ next to the transaction type. You might also want to check out the Auto-set result feature, which allows you to automatically change a transaction’s result after a specified period of time. #### Auto-set transaction result ⚠️ This setting is only available for workspace commissions from advertisers, because partner commissions reflect those values. Auto-set result automatically changes the pending transaction status after a specified period of time. You need to define: Time period – how long to wait before changing the status. Final status – the status to apply after that period (Approved, Rejected, or Pending). This feature is useful if you want to automate status updates after a review window or validation process, for example, approving transactions after 30 days if no rejection has been received. Auto-set result is applied only to pending transactions. You might also want to check out the Auto-approve feature, which approves transactions immediately without waiting for the set time. #### AutoComplete AutoComplete allows you to suggest values to the user while they are typing in a form field. Instead of filling in the full value manually, the system queries an external service and displays relevant suggestions (e.g. city names, street names, product codes). This feature improves the user experience by making forms faster to fill out and reducing input errors. How AutoComplete works The user starts typing into a field, for example City. PalDock runs the scenario attached to that field, which calls an external service. See Connection Creator in Structures. The service responds with a list of possible values. The suggestions are displayed to the user as they type. When the user picks one, the value is filled into the field. The user can still type a value that was not suggested. AutoComplete offers help, it does not restrict what the field accepts. If the value has to be one of a known set, use a Select field or add validation. Setting it up Three things have to line up: The scenario calls the service and passes in what the user has typed so far. The list of suggestions is picked out of the response and stored under a name, for example names. The field is linked to the scenario, and its accessor points at that name, so PalDock knows which part of the response holds the suggestions. If the accessor points at something that is not a list, no suggestions appear and nothing is reported. That is the first thing to check when a field stays silent. Example: city names from OpenStreetMap The field in the structure has the system name city. The scenario sends a GET request to https://nominatim.openstreetmap.org/search with: the value the user is typing, mapped to the city parameter featureType=city format=json limit=5 a User-Agent header, which this particular service requires The response is a list of places. The scenario picks the name out of each one and stores the result as names. On the field, the accessor is set to names. Note the limit=5. A suggestion list is read at a glance, so a long one is worse than a short one, and every extra result costs response time the user is waiting through. Typical use cases Suggesting city or street names from geolocation services. Offering product codes or SKUs from a product feed. Completing company names from a business registry. Providing postal codes based on partial input. What to watch out for ⚠️ AutoComplete depends on external services. If the service is unavailable or slow to respond, suggestions do not load. Keep it fast. The scenario runs while the user is mid-word, so the whole thing has to finish in a couple of seconds to be useful at all. Set a short timeout on the HTTP node. See Limits and timeouts. An outage is not a blocker here. Unlike validation, a failed AutoComplete does not stop the form. The user sees no suggestions and types the value themselves. That is a good reason to use AutoComplete rather than a Select when the list is long and the service is not fully reliable. Watch the call volume. The service is queried while the user types, not once on submit, so one filled form is several requests. Check what your provider allows and what it costs before you put AutoComplete on a high-traffic form. #### Basic visual cues PalDock keeps the same layout everywhere, so once you can read one screen you can read all of them. The workspace picker The top left corner shows which workspace you are in. Switch it and everything changes with it: data, reports, offers, and partners. Nothing is shared between workspaces except the accounts themselves. See One Account, Multiple Workspaces. Layout Three areas, on every screen: Main menu, the left sidebar. Access to every module. It does not change. Top tabs, the horizontal menu. Context for the module you are in, and the tabs differ between preview and edit. Top right controls. Workspace, profile, search, payouts, and adding new items. Preview and edit PalDock has two modes, and the background colour tells you which one you are in. Preview is grey. You are looking, not changing. Data, offers, and settings are visible but nothing you do here saves. Edit is green. You are changing something. Details, settings, and tracking configuration are editable. The colour is the fastest way to answer why a change did not stick. If the background is grey, it was never being saved. Icons that mean the same thing everywhere Tables share a set of controls, and each icon does the same job wherever you meet it: Column icon: choose which columns are shown. See Advanced columns. Layer icon: add a secondary grouping. See Performance reports. Target icon: switch the reporting time basis. Filter button: open the large filter. See Filters. Checkbox icon: select or clear all rows, which is what makes rows plottable in the chart and exportable on their own. Trash icon: remove, always with a confirmation step. #### Breaker The Breaker node caps how many times a loop can repeat. It is what turns a retry into something that finishes. How the count works You set a number of repeats. The flow may pass through the Breaker that many times. On the next arrival, the Breaker stops it. Set it to 2 and the flow goes through twice. The third time it arrives, the run stops there. So the number is how many passes you allow, not how many times it may loop back. With a loop that asks an advertiser for a status, a Breaker set to 6 means six questions asked. What stopping means The run ends at the Breaker. Nothing further happens on that branch, no End node is reached, and no result is written. That has a consequence worth planning for: those leads are neither approved nor rejected. They are simply unresolved. Decide what you want to do with them, because nothing will happen to them on its own. Other branches are unaffected. Only the branch that hit the Breaker stops. Choosing the limit Work backwards from how long the advertiser realistically takes, then divide by your Wait. Answers within minutes: a Breaker of 3 with a Wait of one minute. Answers within a day: a Breaker of 6 with a Wait of four hours. Answers within a week: a Breaker of 6 with a Wait of a day. Add a little margin, but not much. Every extra attempt is another request to the advertiser’s API for a lead that is looking less likely with each one. Why you always want one A loop without a Breaker does not run forever, but the way it ends is worse than stopping cleanly. PalDock allows a single node to run at most thirty times within one run, and past that the whole run fails with an error. An error is meant to mean something broke. A lead the advertiser never got round to deciding on has not broken anything, and you do not want the two mixed together in your logs. In a pingtree there is a second reason. A loop that keeps going holds up the channel, and the pingtree cannot move on to the next advertiser while it waits. Common mistakes No Breaker at all, so the loop ends in an error instead of a decision. A limit set without looking at the Wait. The two only mean something together. Forgetting about the leads that hit the limit. They stay unresolved until you go looking for them. #### Building integrations This page is the standard for how an integration in Connection Creator is built. It applies to a person building one by hand and to an AI agent generating or reviewing one, and it is deliberately stricter than what the editor technically allows. How to integrate anything explains the method: what to do first, second and third. This page explains what a finished integration has to look like, and why. It is written to be checkable. Almost every rule here can be verified by opening a blueprint and looking, which is the point: consistent integrations can be filtered, compared and debugged together, and inconsistent ones can only be read one by one. The rule set at the end carries an identifier for each rule, so a finding can be named rather than described, and most of those rules are checkable by a program. The one idea An integration is a translator, not a repair shop. Its job is to take a lead that is already correct and say it in the advertiser’s vocabulary. Every time an integration does something else, whether that is fixing a malformed value, inventing a field, re-shaping a response or deciding what a good phone number looks like, that work is being done in the wrong place, once per advertiser, and it will be done differently the next time. Three places can do work, and they are not interchangeable: Structure decides what a valid value is: formats, required fields, validation, and any normalisation every advertiser would need anyway. Transform data decides what this advertiser calls things: enum mapping, their date format, their limits, their prefixes. The HTTP node puts the request together: composing values, static values, and type conversion. Every form field arrives as a string, so a number or a boolean is made at the moment the request is built, never earlier. If a transformation would be needed for every advertiser, it does not belong in an integration at all. Fix the structure once and every integration built afterwards gets it for free. Fields and values Map to the closest PalDock field Pick the PalDock field that means what the advertiser’s field means, not the one whose name looks similar. Global fields first, because integrations from the library are built against them and because the same field then means the same thing in every workspace. If nothing fits, a local field is the answer, and it is a workspace-level decision, not something to invent inside one blueprint. Modify the original field, never a parallel one This is the single most common mistake in generated blueprints. When the advertiser needs income_type in their own vocabulary, the mapping is written into {income_type}. Not into income_type_extra, not into income_type_sub, not into income_type_advertiser. ✗ Field: {income_type_sub} source {income_type}, equals full-time → EMPLOYED ✓ Field: {income_type} equals full-time → EMPLOYED A Modify Field section already takes the field’s own value as its source and writes the result back. The parallel field adds a name nobody else uses, a source reference that can go stale, and a second thing to keep in sync. It buys nothing, because the original value is not needed again. A helper field is justified in exactly two cases: The original value is still needed later in the same flow, in its original form. Sending both amount and a capped amount_max is a real case. One source field feeds two advertiser fields that need different transformations. Splitting a full name into two parts is a real case. When you do need one, name it for what it holds and give it the custom_ prefix, as {custom_amount_capped}. Do not name it after the field it was derived from with a suffix bolted on. Compose in the HTTP node, do not compose in Modify Putting two values next to each other is not a transformation. Any field in an HTTP node accepts free text mixed with references, so write it there: ✗ Modify: {custom_permanent_street} = {address_street} + prefix/postfix chain HTTP: permanent_street = {custom_permanent_street} ✓ HTTP: permanent_street = {address_street} {address_street_number} The same goes for a fixed value the advertiser requires, a header built from a token, or a URL assembled from an endpoint key and a path. If there is no condition and no logic, it belongs in the request. Convert types in the HTTP node, never in Modify Every form field is a string. {amount} is “5000”, not 5000, and {consent} is “true”, not true. That is true of every field in every structure, so a type is never a property the value already has: it is something one advertiser’s API asks for and another does not. That puts conversion in the same category as composition and static values. It is part of building the request, so it goes in the request, taken from the picker in the field itself: ✗ Transform data: {amount} to_intHTTP: amount = {amount} ✓ HTTP: amount = toInt({amount}) Two reasons. Opening the HTTP node should tell you the exact shape of every key going out. If half the types are decided in a Transform data node three steps earlier, that is no longer true of any of them, and a difference between two advertisers that is purely about their request format is buried in a node that is supposed to hold their vocabulary. A converted field is also no longer the form’s value. Anything reading it later, a condition, a second request, a reject mapping, reads whatever the conversion left behind rather than what the person filled in. Converting in the request leaves the field alone and gives each advertiser the type they asked for. Use one conversion, not a nest of them: toBool(toString({value})) is a smell, not a technique. And where the advertiser wants a string, write nothing. The value already is one. Parameter names are snake_case {redirect_url} is a parameter the platform reads. {redirectUrl} is a new parameter nobody reads, created by a typo, holding the right value where nothing will ever look for it. The same applies to every field and key you write yourself. When the vocabularies do not line up, choose the answer that keeps the lead alive Advertisers bucket things differently from your form. Employment length is three months, and their API offers 0 or 12. Neither is right. Send 12. Where two vocabularies do not map cleanly and there is no exact option, pick the one that presents the lead as qualifying. The advertiser verifies what actually matters to them later; a lead filtered out at the door for a bucketing difference is a lead nobody gets paid for. Two limits on this: It resolves a gap between two vocabularies. It does not invent data. An answer the person gave as no is never sent as yes. It does not apply to what is being bought. Amount, term and product are the request itself, so send what the person asked for and let the advertiser refuse it. There is one common exception, and it needs agreeing rather than deciding. Where an advertiser publishes a maximum and rejects anything above it outright, sending the maximum instead of the requested figure keeps a lead alive that would otherwise be refused on a formality. Where the advertiser would have made a smaller offer on their own, sending the maximum takes that decision away from them. Ask which of the two they do before capping. Empty and optional values An empty required field is a rejected request at some advertisers, even when they do not care about the value. Fill it with a placeholder. An empty optional field is better left out. Use do-not-send to drop it from the request. Never send the literal string "null" unless the advertiser explicitly documents that they want null. A field that can only ever be invalid is dropped, not patched. Where a value fails the advertiser’s own validation, sending a trimmed or padded version turns a missing field into an invalid one, and an invalid field is refused harder than an absent one. Transformations Format is the structure’s job Before writing a transformation, ask whether the value should ever have arrived in that shape. A regex that repairs a postcode, strips spaces from a phone number, or trims a national ID is validation in the wrong place. It belongs in field validation or in the structure’s own Modify, where it runs once, for every advertiser, before the lead is even accepted. Doing it in the integration means the malformed value still enters PalDock, still goes to every other advertiser unrepaired, and gets patched in fifteen blueprints separately until one of them is missed. In an integration, transform only where this advertiser genuinely diverges from what the form produces. That leaves a short list, and it is the list worth having in a Transform data node: enum and code mapping into their vocabulary their date format their amount or term limits a prefix or format that is theirs specifically conditional values that depend on other fields One Transform data node per flow, and none at all when there is nothing to transform All of it goes in one node, placed before the point where the flow branches. One node holds as many sections as you need, and each section is one field, so there is no size at which a second node becomes necessary. A second Transform data node is justified only when it transforms something that did not exist yet at the first one, such as a value returned by an earlier request. Two nodes acting on form fields, in sequence or on parallel branches, is always a mistake. The rule is one node at most, not one node always. An empty Transform data node, or one holding a section with no rows, is not compliance. It is a step that runs, logs and explains nothing. The same applies to an empty Store response node. If the flow has nothing to transform or nothing worth storing, delete the node. Do not transform the advertiser’s response The response is already data. Use it where it is needed: ✗ Modify: {custom_app_id} = {parsedBody.applicationId} HTTP: .../applications/{custom_app_id}/accept ✓ HTTP: .../applications/{parsedBody.applicationId}/accept Two things are worth taking out of a response, and both are storage rather than transformation, so both belong in a Store response Set node: values that must outlive the run, such as {external_id} and {redirect_url}, and values a later step needs after other steps have run in between, such as a token. The distinction that matters is distance. Storing a value that the very next node reads is a detour with no purpose. Storing a value that three steps and a wait later still needs is exactly what Store response is for. Reference the response directly with {parsedBody...}, {status}, {body} and {headers} whenever you are handling the response of the step being evaluated. Reference a named earlier step only when you genuinely need data from a different request. Reaching into the response Use the index for a single element. {parsedBody.errors.0.error_code} resolves to that element’s value and can be tested, stored or written into a field, as long as the element itself is a string or a number. Without the index it does not resolve. {parsedBody.errors.error_code} comes back as literal text, and literal text is never empty, so is not empty on it is always true and is empty always false. A branch built on that fires on every response, whatever came back, which is how a Ping flow ends up labelling eight rejections in a row as the same reason and never reaching its own success branch. Whether an index is needed depends on the response, not on the field name. A property called errors is a list at one advertiser and a map keyed by field name at another. In the first case {parsedBody.errors.0.code} is right and {parsedBody.errors.code} resolves to nothing; in the second it is the other way round. Nothing in the blueprint says which, so this is one of the few things that has to be read from a real response rather than checked mechanically. What is checkable, without knowing anything about the advertiser, is that one blueprint addresses the same container two different ways. Where {parsedBody.errors.0.code} and {parsedBody.errors.code} both appear in the same integration, the container cannot be both a list and a map, so one of them is silently doing nothing. A reference that resolves to an object or an array resolves to its JSON text, so a regex operator can be pointed at it. {parsedBody} searches the whole parsed response, {parsedBody.non_field_errors} searches only that array. What a pattern cannot do is pick an element out that way: a match against an array tells you the text is somewhere in it, not which element held it, so use an index when you need the value itself. Target the narrowest reference that answers the question: an indexed element, when you know where the value is the array or object that contains it, when the position varies {body}, the raw response as text, when the shape itself varies ✓ {parsedBody.non_field_errors.0} regex_match already registered an element holding a string ✓ {parsedBody.non_field_errors} regex_match already registered that array as JSON text ✓ {parsedBody} regex_match already registered the whole parsed response as JSON text ✓ {body} regex_match already registered the raw response as text The wider the target, the more places a pattern can match by accident. A word that appears in the advertiser’s error message may also appear in a field they echo back from the request, so scope the condition to the part of the response that carries the answer. For {reason_detail}, prefer {body} on an unconditional row. It carries the whole response whatever its shape, so it keeps working when the advertiser adds a field or returns an error nobody has seen yet. Compose from indexed paths only as an additional, conditional row on top of it. Rows do not chain by default Every row in a section evaluates its source against the value the field held when the node started, not against the result of the row above it. Rows are independent unless you connect them explicitly. To read the output of an earlier row, set the Source to that row. The editor inserts a positional reference: {_1} is the result of the first row, {_2} of the second, and so on. The same reference works for any earlier row, not just the immediately preceding one. 1. source {data_city} always → test 2. source {_1} always → … ← reads the result of row 1 3. source {_2} always → … 4. source {_1} always → … ← any earlier row, not only the last Row indexes are renumbered on save, after rows with neither an operator nor a modification are dropped. A reference set before an empty row was removed can end up pointing at a different row than the one it was set to, so re-check chained rows after editing the section. A fallback can therefore sit anywhere in the section, as long as its condition is written against the value it will actually see: Fallback first. Recommended. It sets the default and the specific rows below override it. Their conditions are written against the form’s vocabulary, which is what they read anyway. Fallback last. Only with an explicit {_N} source pointing at the row whose result it should judge. Never place a fallback last with the field itself as source. It re-reads the original value and overwrites the mapping that just succeeded. A regex_match ^\d{4}$ → 1 line at the bottom of a seventy-row bank-code mapping re-read the original four-digit code and reset every correctly mapped lead to bank ID 1, across 549 leads, without a single error anywhere. A negative match listing the values handled above is the one safe way to write a fallback last, and only if it lists them in the form’s vocabulary rather than the advertiser’s. A section that maps full-time → employed and pension → pensioner above, and then ends with regex_not_match ^(employed|pensioner)$, fires for exactly the leads the rows above handled, because the last row still reads full-time, not employed. Every one of them comes out as the default. The same section written as regex_not_match ^(full-time|pension)$ is correct. Operators and modifications The operators are listed in Condition Operators and values, the modifications in List of modifications. Those pages say what exists. Both enums are snake_case: regex_replace, first_regex_match, to_bool. Hyphenated names belong to the previous Connection Creator. They pass the editor’s own check and are then skipped at run time with nothing logged, so the row does nothing and the field keeps the value it already had. What the reference pages cannot say is which slot a value goes into, and that is where half the rows that silently do nothing come from. A valid rule written into the wrong slot runs, matches nothing, and leaves the field as it was, without raising anything. The comparison value goes into value in a Modify row and into output on a connection. Same operator, different slot, and a pattern written into the wrong one never matches. Always, Is empty, Is not empty, Is true and Is false take no comparison value. Leave the slot empty. regex_replace is the only modification that uses both slots: the search pattern in pattern, the replacement in output, with $1 and $2 available. Every other modification leaves pattern empty. replace, math, prefix, postfix, first_regex_match, format_date and modify_date take their argument in output, and the type conversions take nothing at all. Three mistakes account for nearly all of it: a regex match row with the pattern in output instead of value, an Always row with something written into value, and a regex_replace with the pattern and the replacement the wrong way round. One more is worth knowing because of how far it reaches: a row with an operator and no modification fails settings validation, and a step whose settings fail does not run at all. Not the row, the whole node. Every mapping in it stops happening at once, and the run continues as though the node were not there. Watch the braces {parsedBody.status} is a reference. parsedBody.status is a string that will never match anything, and the section silently does nothing. This is the most common reason a Modify Field node appears to be ignored. The same applies to the target of a Modify section and the key of a Set node: written without braces, the name is passed through as a literal and the value lands nowhere. Flow and branching Logic belongs on the arrows A connection is where the flow decides. A node is where the flow acts. ✗ HTTP → Modify (sets a flag when status is APPROVED) → Modify (sets a flag when status is DENIED) → condition on the flag ✓ HTTP → condition {parsedBody.status} equals APPROVED → Store response → condition {parsedBody.status} regex match DEN|CAN → Reject reason Never add a node whose only purpose is to make a decision that a condition already makes. Conversely, never split one decision across several nodes: twenty rejection responses are twenty sections of one Modify Field node, not twenty branches. One connection per node pair At most one connection between the same source and target. Several conditions on one connection are AND-ed; that is what you use when they all have to be true. If you need alternatives, use a Regex match with |, or genuinely separate branches to different nodes. Two arrows between the same two nodes because you had two conditions is always wrong. Find the decision before you write the branch The most common way to break an integration is to guess where the advertiser said yes or no, and guess wrong. There is no house style. Across advertisers the answer turns up in five different places, and more than one puts it somewhere the status code flatly contradicts. Before writing a single branch, look for the answer in all five: A business field in the body. A status, state, result, resolution or accepted field. This is the usual case and the one to prefer. The presence of a URL. Some advertisers say yes by handing over somewhere to send the applicant, and say no by returning the same object with that field null. An error array or map. Empty on success, populated on failure. Reachable only with the right path. The status code alone. Rare, and only safe where the advertiser documents each code as a decision. Some APIs answer with an empty body and nothing else, and then the code is genuinely all there is. Nowhere obvious. Some advertisers return an identical 200 for both and the difference is a field you would not think to look at, such as which page the redirect points to. Two traps worth naming, because each has cost real leads: A status code can mean the opposite of what it looks like. An API whose check is “is this person already known to us” may return 404 to mean we want this lead and 200 to mean we are not interested. Others return business rejections under a non-standard code, or under 400, or under 500. Read the advertiser’s own words, not the RFC. A 5xx is not always theirs and not always a fault. One and the same status code can carry a plain string saying the channel is switched off, and a validation failure naming a field, and a genuine crash. Mapping the whole status code to one reason hides the commercial problem inside the technical one. Cover the business outcomes, overlap nothing, and let the rest fall through Every connection whose condition matches is followed, so alternative branches must be mutually exclusive unless you intend several to run. If no connection matches, the run stops mid-flow and reports Dead End. Cover every outcome the advertiser documents as a business result, then catch the remaining business results with a negative match against the known ones: Approved: {parsedBody.state} Equals APPROVED Rejected: {parsedBody.state} Regex match DEN|CAN Pending: {parsedBody.state} Regex not match DEN|CAN|APPROVED Anchor patterns you mean exactly. Without ^ and $, approved also matches not approved. A catch-all is scoped to the business response, never to the status code. {status} regex_not_match ^201$ is not coverage, it is a funnel: it sends timeouts, auth failures and gateway errors into the same branch as a genuine rejection, and they come out of the report labelled as one. Build the catch-all on a body field, or pair it with the success status code so that only the advertiser’s own answers can reach it. Leaving technical responses uncovered is deliberate. They Dead End, and that is the correct outcome, as below. Say it once Data travels forward through a flow. A step whose result is already available is a step that should not exist again. Auth runs once per flow, when the token stays valid for the later requests. A second Auth node before every HTTP request is duplication, not safety. A transformation runs once. If several later paths need the same transformed value, put Transform data before the point where those paths diverge. A value already stored is read, not fetched again. Repeat a step only for a functional reason: a signature that is request-specific, a token that has expired, a source value that has changed, or a genuinely different output format. Across flows, the rule is the same but the mechanism differs. Ping and Post are separate runs and must never be connected. What passes between them is stored values: if the Ping stored {external_id} or another value the Post needs, the Post reads the parameter instead of asking the advertiser again. A stored value with a lifetime is the exception. An access token that the Ping obtained may have expired by the time the Post runs, so the Post authenticates again rather than reading it. A runtime token belongs in a custom_ parameter for the length of the run. It is never written back into the secrets table, where it would race with parallel runs and bleed across the test and production toggle. Loops There is no retry node. A loop is an HTTP status request with a connection leading back to a Wait for as long as the answer is not final. Every loop has a Breaker. Without one, an advertiser who never decides takes the run into a system limit instead of a clean end. Watch the synchronous limit while you do it, because the visitor is on a loading screen for the whole loop, and the wait multiplied by the Breaker’s count has to fit inside it. Cover every status the advertiser documents, including the terminal ones you do not expect to see. A status missing from the loop conditions is a Dead End waiting to happen. Leave technical errors alone Branch on what the advertiser says, not on the status code. When they return a documented business result under a 4xx or a non-standard code, branch on it and map {reason} from their response. Business rejections arrive under 400, under 409, and under codes that are not in the standard at all. All of them are business outcomes and all of them are mapped. What is forbidden is deriving {reason} from a bare status code the advertiser gave no reason for. {status} regex_match ^(401|403|5\d{2})$ → ERROR invents a reason instead of mapping one. A run that stops on a technical response still produces a result row: PalDock fills {reason} with HTTP 500, HTTP 429 and so on, with status and body in {reason_detail}. Reaching an End node is not required for this. That is why technical responses need no branch at all, and why leaving them to Dead End is not a gap. Two technical failures are easy to miss because they arrive as 200 with a body that reads like a refusal: an authentication error and an expired or wrong credential, both returned inside a normal-looking response object. Neither is the lead’s fault and neither gets a reject reason. A block of them in a report means the integration is broken, and labelling them as rejections hides exactly that. Success and rejection 200 is not acceptance Most advertisers return a rejection with a perfectly normal status code. Decide success on the documented business result in the body. A status code alone is the most common reason an integration reports accepted leads the advertiser never took. Where the advertiser returns both, check both on the same connection: {status} equals 200 and the business field says what it should. Every path reaches an End node, and the End tells the truth Two settings: Success when the other side accepted, Reject when they turned it down. Error is not a setting. It is where a run lands when it never reached an End at all. In the blueprint these are the literal strings success and failed, and only the exact string failed rejects. A typo, a different word, an empty value, all come out as an accepted lead. Every rejection path ends in an End node set to Reject. A rejection branch that ends in a Success node is worse than a broken integration, because nothing looks broken: the reports count leads as sold that nobody bought, and the number is wrong everywhere it is used. Check this on every End node in the blueprint, not only on the one named Rejected. Set both reason parameters {reason} is the category. Short, repeated, in English, and what the reports group by. {reason_detail} is what the advertiser actually said. Free text, passed straight through. {reason_detail} costs one unconditional row copying {body}, and it covers every path at once. Do that before you have mapped a single reason, because those raw strings are the list of responses still to map. All of the reason mapping goes in one Reject reason Modify node. A flow needs a second one only when a second HTTP stage can independently reject the lead, and then both the Modify and its End are qualified with the stage: Reject reason · Offer → Rejected · Offer. No fallback reason {reason} gets a row for each outcome the advertiser actually returns. It does not get an unconditional row at the top setting Unspecified for everything else. The fallback looks like diligence and behaves like a drain. Anything that reaches the node without a mapping, a rejection code added last week, a maintenance page, a response shape that changed, comes out as a normal rejection with a normal-looking reason, and the report gives no sign that a lead was ever misread. A Dead End for the same response reads as what it is: something arrived that this integration does not understand. So the shape is: Connections branch only on outcomes the advertiser documents, plus a catch-all scoped to the business response. Every path that reaches Reject reason is therefore a recognised outcome, and every recognised outcome has its own row. Everything else Dead Ends, loudly. The cost is real and worth naming: when an advertiser introduces a new rejection code, those leads stop producing a report row until someone notices. Dead Ends need watching, exactly as Unspecified would have. The difference is that a Dead End looks like a fault and an Unspecified looks like an answer. Unspecified stays in the vocabulary. It is a mapping, not a default, used when the advertiser’s own documented answer carries no reason, such as accepted: false with nothing else in the body. Unspecified, not Not Eligible This reject reason matters more than it looks. Not Eligible means the advertiser named a condition the lead failed, and it was a condition you could not have checked in advance. A knockout criterion. Unspecified means the advertiser rejected the lead and did not say why. The judgement is easier to copy than to define, so here is how it falls out on the kinds of answer advertisers actually return. Not Eligible, because a condition is named: a documented criteria check that comes back as unsatisfactory or does not meet requirements an internal knockout code the advertiser publishes with a meaning, such as a register or authority check a numeric lead status the advertiser documents as refused by knockout scoring employment history too short, or a licence or registration the applicant does not hold Unspecified, because nothing is named: rejected, declined, not acceptable, unsuccessful, or a single-word refusal code accepted: false with nothing else in the body a two-letter internal code with no published meaning no interest, or an application the advertiser will not process further without saying why an empty body under a status code the advertiser documents as a refusal A flat refusal with no stated reason is Unspecified. Every time. It is worth checking Unspecified from time to time, unlike Not Eligible, because it collects the advertiser’s own vague answers, and a change on their side can start landing there. The reason to be strict about this is not tidiness. Unspecified in a report is a bill you can present to the advertiser: this many leads, refused, no reason given, send us reason codes. Not Eligible reads as a reason that was already given and understood, so nobody ever asks, and the information is lost permanently. Using Not Eligible as a general-purpose rejection bucket quietly removes the leverage the report exists to create. The same applies to any specific reason: map it only when the advertiser actually said it. Pick reasons from the standard list rather than typing them, so the spelling groups. See Reject reason for the full list and what each one means. Naming Good naming means the same step can be filtered and compared across every integration at once. That is what makes logs and audits possible. Node names Keep titles short. A title describes the purpose of the step, not what is already visible from the node type or its configuration. Start node: leave the title empty Main HTTP request in a Ping flow: Ping Main HTTP request in a Post flow: Post Main HTTP request in a Post Verify flow: Verify Data transformation: Transform data Response storage: Store response Reject mapping: Reject reason Authentication request or preparation: Auth Status request: Status Offer request: Offer Accept request: Accept Create request: Create Wait: Wait 3s, Wait 10s Breaker: Breaker 3x, Breaker 5x Successful End: Success Failed End: Rejected The Start node needs no title: its type says Start and its flow says which flow it begins. The main HTTP request is the exception that must always be named. A flow may hold several HTTP nodes, and the one performing the actual Ping, Post or Verify is named for it so it can be filtered across every integration in the logs. Repeated steps Prefer a meaningful qualifier over a number: Status after accept, Offer after verify. Use a numeric suffix only when two requests genuinely do the same thing with no useful distinction: Offer 1, Offer 2. Never Get status2, Request 2 or HTTP 3. Use the shortest unambiguous name. Create is enough when there is only one create operation. Store nodes A Set node that stores values from a response is always Store response, whatever it stores: {external_id}, {redirect_url}, a token, a temporary process ID, a price. The fields inside explain the rest. The advertiser’s persistent ID for the lead goes into {external_id}. Temporary identifiers go into a custom_ parameter. URLs and secrets Base URLs are integration keys, not text in an HTTP node: {endpoint} = https://api.example.com HTTP node: {endpoint}/v1/applications No trailing slash on the endpoint, paths beginning with /. A genuinely different host gets its own key, such as {endpoint_auth}. Never hardcode production credentials in a blueprint. Basic Auth always uses {username} and {password}. If the header must be built by hand, Base64 encode {username}:{password} at run time. Do not store a pre-encoded value as a secret: it cannot be rotated one half at a time, it cannot be paired cleanly with a test value, and nobody six months from now will know which half changed. Secret names come from the allowed list. custom_* is the only free space, and a recurring value that lands there fragments into a different name in every blueprint. Flow IDs Post flow uses 1-*, Ping flow uses 2-* where practical. This one is a convention, not a requirement, and an existing blueprint is not rewritten for it. A Ping flow exists only alongside a Post flow. Further independent flows use 3-, 4-, and so on. Independent flows are never connected. The node id itself is not decorative. The canvas reads it to work out which flow a node belongs to, and refuses a connection between two nodes in different flows, so a generated id has to match the graph it describes. Anti-patterns Each of these appears in real blueprints, and each has a one-line correction. Fields and transformation A parallel field, mapping income_type into income_type_sub → map into {income_type} itself A regex repairing a postcode, phone or ID inside the integration → fix it in the structure’s validation or Modify {custom_permanent_street} built from street plus number in Modify → {address_street} {address_street_number} in the HTTP field Copying {parsedBody.x} into a custom field the next node then reads → use {parsedBody.x} in the next node Two or three Transform data nodes on the same flow → one node, before the branch, with as many sections as needed An empty Transform data or Store response node → delete it A row with an operator and no modification → complete it or delete it, or the whole node stops running A hyphenated modification name → use the snake_case enum A fallback line placed last with the field as its own source → put it first, or give it a {_N} source A negative fallback written in the advertiser’s vocabulary instead of the form’s → list the form’s values A regex match row with the pattern in output instead of value → the pattern goes in value in a Modify row, in output on a connection to_int or to_bool as a Transform data row → toInt({amount}) in the HTTP field; form fields are strings, so the type belongs to the request, not to the field. toBool(toString({value})) → one conversion, or none Sending "null" for a missing optional value → do-not-send Repairing a value that can only ever be invalid → drop the field instead {redirectUrl} where {redirect_url} was meant → snake_case, always Graph and branching A Modify node whose only job is to set a flag for a later condition → put the condition on the connection A Modify node per rejection response → one Reject reason node with one section per response Two arrows between the same two nodes with different conditions → one arrow, or a regex, or separate branches Branching on the advertiser’s status without a catch-all → Regex not match against the known values A catch-all built on {status} regex_not_match ^201$ → scope it to the business response, or pair it with the success status code A regex against {body} when the value always arrives in one known field → target that field, so the pattern cannot match elsewhere in the response The same container addressed with and without an index in one blueprint → decide which it is and use it consistently A connection on {status} 400 or 500 whose Reject reason is derived from the status code → delete it, PalDock fills those in. Keep it only when the body carries a documented business result. An Auth node before every HTTP request → one Auth per flow, while the token is valid Post re-fetching something the Ping already stored → read the stored parameter A loop without a Breaker → add Breaker 3x Outcomes and configuration A rejection branch ending in an End set to Success → set it to Reject An unconditional Unspecified row at the top of {reason} → remove it and let unrecognised responses Dead End Not Eligible on a refusal with no stated reason → Unspecified A technical failure mapped to a reject reason → leave it uncovered format: application/json set on one node and assumed on the rest → set it explicitly on every node sending a JSON body A runtime token written back into the secrets table → keep it in a custom_ parameter for the run Preflight checklist Before a blueprint is finished: Sources API documentation read, and real request and response logs reviewed where available At least one acceptance and one business rejection tested in the run log Where the documentation and the observed responses disagree, the observed behaviour wins, and the difference is written down next to the blueprint Fields Global fields used wherever one fits Modify writes into original fields; no parallel _sub / _extra fields without a stated reason No formatting repair that belongs in the structure Composition and static values are in the HTTP node, not in Modify Bucketing gaps resolved in the lead’s favour, and any cap agreed with the advertiser Empty optional fields dropped with do-not-send, never sent as "null" Every parameter name snake_case Structure of the flow At most one Transform data node per flow, before the branch, and none if there is nothing to transform No empty nodes of any kind, and no row with an operator but no modification Auth appears once per flow Nothing is recomputed that an earlier step already produced The advertiser’s response is used directly, not copied into a field the next node reads Conditions target the narrowest reference that answers them The same container is addressed the same way throughout Store response holds {external_id} and {redirect_url} where returned Ping and Post are not connected Every loop contains a Breaker, and the wait times fit inside the synchronous limit No duplicate source → target connections; node and edge IDs unique; no orphan nodes Outcomes The decision was looked for in the body, in the URL, in the error object and in the status code before any branch was written Success is decided on the business result, not on the status code alone Every documented business response leads somewhere; the catch-all is scoped to the business response Technical responses are left uncovered and Dead End Branch conditions do not overlap unintentionally Every business path reaches an End node Every rejection End is set to Reject, not Success {reason} mapped for every documented outcome, from the standard list, with no unconditional fallback row {reason_detail} set unconditionally from {body} Unspecified used where the advertiser gave no reason; Not Eligible only where they named a failed condition No {reason} derived from a status code alone Configuration format set explicitly on every node sending a body Every enum value taken from the current lists; no value the editor does not offer Timeouts, waits and repeats inside their limits No credentials or base URLs hardcoded; Basic Auth uses {username} and {password} Naming Main HTTP nodes named Ping, Post or Verify Start titles empty Store nodes named Store response, transformation nodes Transform data, reject mapping Reject reason Wait and Breaker titles include their value Rule set for AI agents Deterministic rules for generating or reviewing a blueprint. Each carries an identifier so a finding can be named. Rules marked [M] are checkable against the blueprint JSON alone; rules marked [J] need judgement about what the advertiser meant, and are the review. Node types, operators and modifications are defined by the schema and by the pages linked above, so this list does not repeat them. An agent MUST NOT emit a node type, operator or modification that the schema does not define. Fields F-01 [M] MUST write a mapped value into the original form field. MUST NOT create a *_sub, *_extra, *_new or similarly suffixed target field. F-02 [J] MAY create a helper field only when the original value is still needed unchanged later in the same flow, or when one source feeds two differently transformed targets. It MUST use the custom_ prefix and MUST be named for its content. F-03 [J] MUST NOT add a transformation whose purpose is to correct a malformed value. Format validation belongs to the structure. F-04 [M] MUST place value composition, static values and type conversions in the HTTP node. MUST NOT emit a type conversion (to_int, to_float, to_bool, to_string) as a Modify or Transform data row: form fields are strings, so the type is a property of this advertiser’s request, not of the value. MUST NOT nest conversions. F-05 [J] When no advertiser option matches exactly, MUST select the option that presents the lead as qualifying, except for amount, term and product, and except where it would invert an answer the person gave. F-06 [M] MUST use do-not-send for empty optional fields. MUST NOT send the string "null". F-07 [J] Where a field can only ever be invalid, MUST drop it rather than sending a repaired or placeholder value. F-08 [J] MUST map to a global field wherever one fits. Transformation T-01 [M] MUST use at most one Transform data node per flow, placed before the first branch. A second is allowed only when it operates on data produced by an earlier step in that flow. T-02 [M] MUST NOT emit a Transform data or Store response node with no rows. T-03 [M] MUST reference {parsedBody...}, {status}, {body}, {headers} directly in the step that consumes them. MUST NOT copy a response value into an intermediate field that the very next node then reads. T-04 [M] MUST place a fallback first in the section, or last with an explicit {_N} source. MUST NOT place a fallback last with the field itself as source unless its condition is written against the form’s vocabulary and cannot be true for a value a row above already mapped. T-05 [J] MUST include the index when addressing a single element of an array: {parsedBody.errors.0.code}, never {parsedBody.errors.code}. Whether a container is a list or a map keyed by field name is a property of the response, not of the name, so this is read from a real response. T-05b [M] MUST address the same container the same way throughout one blueprint. Where both an indexed and a keyed form appear, one of them resolves to literal text. T-06 [C] SHOULD target a regex operator at the narrowest reference that answers the condition. Object and array references resolve to their JSON text and are valid targets, but the wider the target the more places a pattern can match by accident. T-07 [M] MUST write the comparison value into value in a Modify row and into output on a connection. MUST leave it empty for always, is_empty, is_not_empty, is_true and is_false. T-08 [M] MUST write the search pattern into pattern and the replacement into output for regex_replace. MUST leave pattern empty for every other modification. T-09 [M] MUST leave output empty for the modifications that take no argument, and MUST fill it for the ones that do. T-10 [M] MUST write references in braces, with no whitespace inside them. A reference without braces is a literal string that will never match. Graph G-01 [J] MUST express decisions as conditions on connections. MUST NOT create a node solely to enable a later condition. G-02 [M] MUST have at most one connection per source → target pair; multiple conditions on one connection are AND-ed. G-03 [J] MUST make alternative branches mutually exclusive, and MUST include a catch-all Regex not match branch against the known business values. G-04 [M] MUST NOT build a catch-all on the status code alone. MUST scope it to a body field, or combine it with the success status code. G-05 [J] MUST NOT derive {reason} from a status code alone. MAY branch on a 4xx or non-standard status when the advertiser returns a documented business result in the body. G-06 [M] MUST NOT duplicate Auth within a flow while the credential remains valid, and MUST NOT connect flows. G-07 [M] MUST include a Breaker in every loop, with the count in its title. G-08 [M] Node IDs and edge IDs MUST be unique; no orphan nodes; every business path MUST reach an End node. G-09 [M] Node IDs MUST be {flow}-{position} and consistent with the actual graph. G-10 [M] MUST NOT emit a node type that the backend does not implement. Outcomes O-01 [J] MUST base the success branch on the advertiser’s business result, alone or combined with the status code, never on the status code alone. O-02 [M] Every End node on a rejection path MUST carry the literal failed. Any other value, including a typo, is read as an accepted lead. O-03a [J] MUST map {reason} from the standard list for every documented rejection outcome. O-03b [M] MUST NOT add an unconditional row to {reason}. O-04 [M] MUST set {reason_detail} from {body} on an unconditional row. Another field MAY be added as a further conditional row on top. O-05 [J] MUST use Unspecified when the advertiser’s documented answer gives no reason. MUST use Not Eligible only when they name a specific failed condition. O-06 [M] MUST collect all reason mappings into a single Reject reason node per rejecting HTTP stage. O-07 [J] MUST NOT map a technical failure to a reject reason. Leave it uncovered. Schema and limits These are not style. Each one either fails validation or is silently altered on save. S-01 [M] A Modify row MUST have a modification. A row with an operator and no modification fails settings validation, and a step whose settings fail does not run at all: not the row, the whole node. S-02 [M] Operators and modifications MUST come from the current snake_case enums. Hyphenated names pass the editor’s own check and are then skipped at run time with nothing logged. S-03 [M] format, method, parser, notsend and convert_data MUST hold values the editor offers. A Breaker count that fails its pattern is silently replaced with 1. S-04 [M] Limits: HTTP timeout at most 295 seconds, Repeater at most 20, Wait at most one year, 50 steps per scenario. Two more are runtime rather than structural: 30 runs of one step per scenario run, and the synchronous delay ceiling before a run goes asynchronous. S-05 [M] A Set key and a Modify target MUST be written in braces. S-06 [C] A row reference MUST be written as {_1}, which is what the editor inserts. Row indexes are renumbered on save after empty rows are dropped. P-01 [M] Parameter names MUST be snake_case. Configuration C-01 [M] MUST set format explicitly on every node sending a body. It is not inherited. C-02 [M] Base URLs MUST live in integration keys. Basic Auth MUST use {username} and {password}, encoded at run time. Credentials MUST NOT be hardcoded and a pre-encoded blob MUST NOT be stored. C-03 [M] A runtime token MUST go into a custom_ parameter and MUST NOT be written back into the secrets table. C-04 [M] Secret names MUST come from the allowed list. custom_* is the only free space. C-05 [M] A body format that needs nesting MUST be written as data.field keys; the editor produces a flat object otherwise and the request throws. Naming N-01 [M] Every flow MUST contain one HTTP node named for the flow: Ping, Post or Verify. Start titles MUST be empty. N-02 [M] Response Set nodes MUST be named Store response; transformation nodes Transform data; reject mapping Reject reason, qualified only when a flow has several rejecting stages. N-03 [M] Wait and Breaker titles MUST contain the configured value. N-04 [C] SHOULD use 1-* for Post flow IDs and 2-* for Ping. MUST NOT report a deviation as a finding. Review output When reviewing, report findings by severity, naming the rule and the node: Critical, the integration is broken or misreports outcomes: O-02, T-10, C-01, C-02, C-05, G-08, G-10, S-01, S-02, P-01. High, wrong data is sent or rejections are mislabelled: F-01, F-06, T-04, T-05b, T-07, T-08, T-09, G-04, G-07, G-09, O-03b, O-04, O-05, O-07, C-03, C-04, S-03, S-04, S-05. Medium, duplication and structure: F-04, T-01, T-02, T-03, G-01, G-02, G-06, O-06. Convention, naming and scope: N-01 to N-04, T-05, T-06, S-06. MUST NOT reorder a flow to fix a naming issue, and MUST NOT report a flow-id convention as a finding. What a checker cannot decide Thirty-six of these rules are checkable against the blueprint JSON alone. The twelve marked [J] all turn on the same question: what did the advertiser actually mean. No schema tells you whether a one-word refusal names a condition or merely says no, whether a regex repairing a postcode belongs here or in the structure, or whether a container is a list or a map. Those are the review, and they are where attention is worth spending. Everything above them should already have been caught before a person opens the blueprint at all. #### Categorization Any entity in a workspace can be classified: affiliates, advertisers, offers, and more. Three ways to do it. Country, single select Category, single select Tags, multi select Categories and tags are yours to define. The country list is fixed. What categorisation is for It is not decoration. Country, category, and tags are filters and grouping dimensions in every report, which is what makes them worth setting when an entity is created rather than later. Backfilling tags across two hundred affiliates so you can compare them by type is a bad afternoon. They also decide where your offers and your program appear in the PalDock catalogue, which is how partners and advertisers find each other. See Settings. Global entities An entity with no country is treated as Global. It appears whatever country you filter by, rather than disappearing from every filter. That is usually what you want for an offer that runs everywhere. Set a country when the entity genuinely belongs to one market, because a country set wrongly is worse than one left empty. Choosing between category and tag Category is one value, the main classification. What kind of thing this is. Tags are many, and are for everything else. How a partner works, which campaign an offer belongs to, which team looks after it. If you find yourself wanting two categories, that is what tags are for. Example values These are the categories we use in the offer and partner marketplace. Yours do not have to match. Offers Adult Baby Beauty Business Education Electronics Fashion Finance Food Health Hobbies Home Languages Lifestyle Media Mobility Pets Real Estate SaaS Shopping Sports Travel Partners Cashback Comparison Content Coupon Email Influencer Leadgen Mobile App Network Paid media Product Catalog #### Columns explained This page explains how the calculated columns in reports are worked out. Columns that hold a plain value, such as names, identifiers, dates, tags, countries, and the fields your own forms collect, are not listed here. For the identifiers behind a row, see Conversion IDs explained. For choosing which columns are on screen, see Advanced columns. Rules that apply to every column Four things change what a number says, whatever column it sits in. Currency Reports convert every amount into the workspace currency and show one total, because a report with a different currency on every row cannot be read. Transactions, balances, and invoices stay in the offer currency, because that is what actually gets paid. See Currency. What counts as a click or a lead Three different numbers, three different meanings: Gross: everything that arrived, duplicates included. Clicks and leads: what was counted, after deduplication. Unique leads: how many were the first from that person in the product. See Origin Deduplication. Time basis and result filter The money and transaction columns follow the reporting time basis and the result type filter. Click and lead columns follow neither, since they have no transaction and no result. This is the usual reason two people reading the same report get two different totals. The partner’s view For an affiliate, Costs is labelled Revenue, because what you pay is what they earn. For an advertiser, Revenue is labelled Costs. The number is the same, the label follows who is looking. [table id=9 /] #### Commission amount The commission amount defines what a transaction is worth, both for you and for your partners. There are three types. 1. Fixed amount A value that is always used, no matter what arrives in tracking. Only digits and the . separator are allowed. Use it for standard CPA and CPL deals. 2. Percentage On workspace commissions, the percentage is taken from the value received in tracking. Value 100 with a 10% commission gives 10. On partner commissions, the percentage is taken from the workspace commission amount. A workspace commission of 10 with a partner commission of 50% pays the partner 5. What the affiliate sees follows from that: If the workspace amount is fixed, the affiliate sees the calculated amount, not the percentage. You receive €100, the partner share is 20%, the affiliate sees €20. If the workspace amount is a percentage, the affiliate sees a percentage of the value. You receive 5% of the value, the partner share is 50%, the affiliate sees 2.5% of the value. 3. Calculation A formula that PalDock evaluates when the transaction is created. Use it when the amount depends on what the advertiser sends. Fields you can use {value}: the order value from tracking. Example: 0.05 * {value} {commission}: the payout amount itself, when the advertiser tells you what they will pay rather than what the order was worth. Example: {commission} {parent}: on partner commissions, the workspace commission amount. Example: 0.5 * {parent} {field_name}: any field from the lead’s structure, written exactly as the field is named. Example: 0.02 * {loan_amount} Formulas accept lowercase letters, digits, ., brackets, and + - * /. Combining several fields The formula is not limited to one field. You can use everything the advertiser sends in the same calculation, so the payout reflects what you are actually being paid on. Typical deductions from the reported amount: Tax or VAT Bonuses and free credit, which the advertiser does not pay you for Discounts and vouchers Chargebacks, fees, or any other cost you carry Example for a gaming advertiser paying 25% of net revenue: 0.25 * ({value} - {bonus} - {tax} - {fees}) Two things to keep in mind: Every field in the formula has to arrive with the conversion. One missing field makes the whole amount 0, not just that part of it. Agree the full list with the advertiser before you go live. Wrap deductions in brackets. 0.25 * {value} - {bonus} subtracts the bonus after the percentage, which is almost never what you want. Setting the amount in a scenario {commission} is filled in two ways. The advertiser sends it in the tracking request, in the commission parameter. You set it yourself in the tracking scenario, which is the more common case. In the scenario, use a Set node to write the amount into {commission}, and put conditions on the connections leading to each node to decide which amount applies. Then set the commission formula to {commission} and every lead gets the amount its own path produced. This is how you pay tiered amounts without creating a separate commission for each tier. Example: a consumer loan advertiser pays more for larger loans. One scenario, three Set nodes: Connection condition {required_amount} is less than 5000, Set node writes 40 into {commission} Connection condition {required_amount} is 5000 or more and less than 8000, Set node writes 70 Connection condition {required_amount} is 8000 or more, Set node writes 90 The commission formula stays {commission} for all of them. Change the tiers by editing the scenario, not the commissions. The same pattern works with any field the advertiser sends, such as product category, country, or plan name. Use {value} when the deciding field is the order value itself. See Connection Creator in Tracking. When a value is missing If the request does not contain a field your formula needs, the amount is 0 and a transaction is still created. Watch for this when you switch an advertiser to a percentage or a formula. Agree with the advertiser which fields are sent with every conversion, and that they are sent even when they are zero. Check the conversion log after the first live conversions. Keep a fixed amount as the fallback commission if the advertiser is unreliable. Keeping it readable Use Display amount to show a clean label such as “5%” instead of the formula. Use Commission detail for a short note in the commission table. A common case: you receive 10% of the value from the advertiser and want to pay partners 5% of the same value, not 5% of your commission. Set the partner formula to 0.05 * {value} and the Display amount to “5%”. Where to set it In the Commissions section, to edit several offers at once. In Offer settings, when you only need one offer. PalDock calculates reporting metrics such as ROI from the difference between your amount and the partner payout. See also Commission groups for paying different affiliates differently. #### Commission conditions to create Transactions ⚠️ A commission is simply a rule that defines when and how a transaction should be created from a conversion. The settings below are only available for workspace commissions from advertisers, because partner commissions reflect those values. Conversions on their own are only performance metrics without a payout. Conditions decide which conversions a commission applies to, and therefore when a transaction is created. Conversions reach PalDock in two ways: Created by PalDock, such as clicks, leads, and sends. Received through tracking, such as prospects and sales, via pixel, postback, Tracking API, or manual import. Available conditions Offer: choose one or more offers (required). Advertiser: choose one or more advertisers. Conversion type: the type of conversion that triggers the commission, such as click, lead, send, prospect, sale, or a custom type. Source: all sources, or only one, such as affiliate link, iFrame, or API. Channel: when the offer uses Pingtree, you can name each channel and reference that name here. How the conditions are evaluated A commission applies when every condition either matches the conversion or is left empty. Empty means “any”. Source is read from the original click or lead, not from the conversion that arrived last. A sale sent by postback still counts as coming from the affiliate link that started it. When several commissions match the same conversion, see How PalDock picks a commission. Conditions are not the only check Even a matching commission creates no transaction if: It is inactive or outside its active period. See Commission status. Its recurrence limit has been reached. The conversion was deduplicated on the advertiser’s external ID. What the transaction looks like The conditions decide whether a transaction is created. What it looks like is set elsewhere: Commission amount sets the value. Transaction type sets the type. Without it, a prospect conversion creates a prospect transaction and everything else creates a sale. See Prospect + Sale vs Pending Sale. #### Commission detail If you have multiple commissions for the same goal, or are using a calculation that you want to clarify, you can use the Commission detail field to add a short descriptive note. This helps distinguish similar commissions or make the purpose of a formula clear at a glance. The Commission detail appears directly in the commission table, so it should be concise, ideally just a few words. You might also want to check out the Display amount feature, which can simplify how the payout value itself is shown. #### Commission group Commission groups let you pay different affiliates different amounts for the same offer, without creating a separate offer or a separate commission for each of them. Groups apply to partner commissions only. A workspace commission always exists once per offer and conversion type, because there is nothing to segment on your own side. A group can contain one or many affiliates. An affiliate can belong to only one group. Affiliates you have not put anywhere belong to the Default group. What gets created You never create partner commissions by hand. PalDock keeps them in sync for you. When you create a workspace commission, PalDock creates one partner commission under it for the Default group and for every other group. When you create a new group, PalDock creates a partner commission for that group under every existing workspace commission. All of them start as inactive, so nothing is paid out before you set the amounts. What the partner commissions inherit Each partner commission copies the conditions of the workspace commission above it: offer, conversion type, source, channel, active period, transaction type, and auto-approve. Those fields cannot be changed on the partner commission, and any later change to the workspace commission is passed down automatically. What you set per group is the part that differs: The amount The display amount and detail Whether the commission is active for that group Which one applies An affiliate is always paid by the commission for their own group. There is no fallback. If the commission for that group is inactive, the affiliate gets no transaction. The commission of another group is never used instead. Activate the commission in every group that should be earning on the offer, not just in the Default group. See How PalDock picks a commission. Working with groups Start with the Default group and add more only when you actually need to pay someone differently. Deleting a group moves its affiliates to the Default group, so they are paid by the Default group commission from then on. Moving an affiliate between groups changes what they earn on future transactions. Transactions already created keep their amount. Groups are workspace-wide, not per offer, so one group covers all your offers at once. #### Commission ID Every commission in PalDock has its own ID. Sending it with a tracking request tells PalDock exactly which commission to apply, instead of letting the system choose. When you need it You have more than one commission for the same conversion type and the advertiser has to say which one applies. You pay different amounts for different products or plans inside one offer. You want the recurrence limit counted separately for each commission, because the limit is counted per commission. You want deduplication on the external ID to allow a second conversion for a different commission. See below. If you only have one commission per conversion type, you do not need it. How to send it Parameter name: commission_id Format: the commission UUID, for example 9e321d3b-3690-4100-821d-86476cc4c2fb Supported in the tracking pixel, S2S postback, and the Tracking API Not used in the affiliate postback, which sends results out rather than in Alternatively, send commission_code with the commission’s own text code instead of the ID The parameter is optional in every request. See Tracking parameters for the full list. Commission code Instead of the Commission ID, you can send a commission code: a short text label you set on the commission yourself. It works as an alias, so commission_code=premium-plan does the same as sending that commission’s ID. It is easier to read and easier for advertisers to implement than a UUID. It does not change any behaviour. Everything on this page applies to the code the same way it applies to the ID: the conditions are still checked, deduplication still works per commission, and the recurrence limit is still counted per commission. If you send both, the Commission ID wins. Use the code when the advertiser maps their own product names to your commissions. Use the ID when the request is generated by a system that can store it. What happens when you do not send it When neither the Commission ID nor the commission code is sent, PalDock falls back to commission order: If type is sent, the first commission in the list for that conversion type is used. If neither is sent, the first commission in the list is used. See How PalDock picks a commission. What happens when the ID does not fit The Commission ID does not skip the commission conditions, it only narrows the choice to one commission. That commission still has to match the conversion. If the commission belongs to a different offer, conversion type, channel, or source, it will not be applied and no transaction is created. The request itself is still accepted and the conversion is still recorded. Check the conversion log to see that no transaction was created. Always send an ID that belongs to the same offer as the conversion. Effect on deduplication The Commission ID changes how deduplication on the advertiser’s external ID works. Without a Commission ID: a second conversion with the same external ID is refused, no matter which commission would apply. With a Commission ID: a second conversion with the same external ID is refused only if that specific commission already created a transaction for it. A different commission can still be applied. This is useful when one order should create two transactions, for example a prospect and a sale, and both arrive with the same external ID. #### Commission order Order sets the sequence in which commissions are applied to a conversion. What decides which commissions run Every commission whose conditions match the conversion is applied. One conversion can therefore create several transactions. A Commission ID in the tracking request narrows this to that one commission. Order does not decide whether a commission is used, only when it is processed. See How PalDock picks a commission. How the list is ordered Order is kept separately for each offer and conversion type, so moving a commission up affects that offer and that type only. Workspace commissions and partner commissions have their own order. Partner commissions are chosen by commission group, not by position. A new commission is added to the end of its list. Why the sequence matters Transactions are created in this order, so it is also the order you see them in and the order in which they are sent out through the Tracking API. Put the commission you consider the main one for that conversion type first. See Multiple Commissions for the Same Conversion Type. #### Commission schedule You can set up multiple Commission schedules, where you define: From date To date Which commission group it applies to Amount Amount type (fix, %, calculation) Display amount These changes cannot overlap. Once one period ends and no subsequent change is set, the default amount will be used. #### Commission status A commission can have two statuses: active or inactive.In practice, in the commission table: Active commissions have any amount or calculation filled. Inactive commissions have a dedicated commission type marked with 🚫. If you want to create a transaction from a commission without any payout – for example, just to record a microconversion, you can enter “0” in the amount. You can also make a commission active only for the workspace or only for affiliates (and vice versa).Just be aware that if you pay affiliates for leads but only receive a payout from the advertiser for sales, you risk a loss if those leads do not convert well enough. #### Condition Operators and values Operators are used wherever PalDock compares one value against another: Connections in the Connection Creator Modify Field Table filters Pingtree filters The set is the same everywhere, with one exception noted below. Operators Most operators need one value to compare against. A few need two, and some need none at all. Comparing Equals : the two values are the same Not equals : the two values are different Is less than : lower than the given value Is less than or equals : lower than or equal to it Is greater than : higher than the given value Is greater than or equals : higher than or equal to it Is between : between two boundaries, boundaries excluded. Needs a second value Is between (inclusive) : between two boundaries, boundaries included. Needs a second value Text Contains : the text contains the given substring Does not contain : the text does not contain it Starts with : the text begins with it Ends with : the text ends with it Regex match : the value matches the given pattern Regex not match : the value does not match it State Is true : evaluates to true. No value needed Is false : evaluates to false. No value needed Is empty : empty string, empty list, or nothing at all. No value needed Is not empty : has some value. No value needed Modify Field only Always : always applies. Use it when the change should happen unconditionally, with no condition to write Field value The value you compare against is a plain text field, but it also accepts a regular expression. One condition can then cover several cases, so you do not have to build a separate step for each of them. Compare the two. A single value, in Modify Field: Source: this field Operator: Equals Value: approved Operation: anything Output: anything Several values at once, using a pattern: Source: this field Operator: Regex match Value: approved|rejected Operation: anything Output: anything The second one does the work of two steps. With ten possible statuses it does the work of ten, and everything stays visible in one place instead of being spread across the canvas. Note the operator. Equals compares the text exactly, so approved|rejected would be treated as one long string and would never match anything. Patterns need Regex match. The Field setting only appears when the Source is set to another field. Patterns worth knowing | for alternatives, as in approved|rejected .* for anything, as in app.* ^ and $ to anchor to the start and the end, as in ^approved$ Standard regular expressions are supported, so anything you would normally write works here too. The anchors matter more than they look. Without them, approved also matches not approved, and a rejection quietly travels down the success branch. #### Connection Creator in Integration An integration scenario sends a lead to an advertiser and processes the answer. It starts when a lead reaches an offer, either directly or through a pingtree. Everything else on this page is a variation on the same three steps: put the data in the shape the advertiser wants, send it, and read the answer. One integration is one advertiser and one channel An integration covers a single advertiser through a single channel. That matters because the same advertiser usually appears in your pingtree more than once, and each of those channels is its own integration. They are duplicates. The scenario, the nodes and the mapping are identical, and the only thing that differs is a value: a different token, and with it a different price for the lead. Buying at one price is one channel, buying at another is a second channel with a second token. So build the integration once, get it working, then duplicate it per channel and change the credentials. Do not rebuild the logic each time, because then a fix has to be made in several places and eventually will not be. In an auction, the integration must return {price}. The pingtree needs it to compare bids and decide who wins. Without it, the integration cannot take part in an auction at all. Store it from the ping response the same way you store anything else. The two flows A Start node has a flow. In integrations there are two, and each is a separate path with its own Start and its own End. Ping asks whether the advertiser wants the lead, and at what price. Nothing is created on their side. Post actually submits the lead. Never connect them. They are two flows on one canvas, not two halves of one flow. Not every advertiser needs both. If they only accept submissions, build the Post flow and leave it at that. If they support a pre-check, the ping usually calls a lighter endpoint and only needs to answer one question: yes or no. Some advertisers add a third step, where the lead has to be confirmed by a code sent to the customer. That gets its own Start node too. See Verification below. What the scenario has to give back Sending the lead is half the job. The answer has to be stored, or the lead is delivered and then lost. Two values matter almost every time: {external_id}, the advertiser’s own ID for the lead. Without it you cannot match a later postback, so the conversion never gets confirmed. {redirect_url}, where the customer goes next, if the advertiser hands back a link. Store them with a Set node placed after the HTTP node, reading straight from the response, for example {external_id} = {parsedBody.leadId}. The simplest integration One flow, four nodes: Start, flow Post. Modify to put the data in the advertiser’s shape. HTTP, a POST with the lead in the body. Set to store the response, then End, success. The condition sits on the connection leaving the HTTP node. It is what decides whether the lead was accepted, so make it specific: {status} equals 201 {parsedBody.status.message} contains Created All conditions on one connection must be true for it to be followed. Checking the status code alone is the single most common reason an integration reports accepted leads the advertiser never received. Preparing the data The Modify Field node before the request does the unglamorous work. Four things come up constantly. Translating values. Your form stores full-time, the advertiser expects employed, or 1, or EMPLOYMENT. One Modify Field node holds all of these mappings, one section per field. This is why the node exists: keep the translation in one visible place instead of burying it in the request body. Capping values. The advertiser accepts loans up to a maximum, and your form allows more. Replace anything above the limit with the limit, rather than sending a value that will be rejected. Filling required fields that are empty. Some advertisers reject a request outright when a field is missing, even when the field is irrelevant. Replace the empty value with a placeholder. Reformatting. Adding an international prefix to a phone number, changing a date format, splitting or joining values. Authentication Three patterns cover almost everything. A static token goes straight in a header or a query parameter as {token}. Nothing to build. Basic auth needs the credentials joined and encoded first. A Set node builds the string, then a Modify Field node applies to-base64, and the result goes into the header as Basic {auth}. A token you have to fetch needs its own request before the real one. The Post flow starts with an HTTP node calling the auth endpoint, a Set node stores {token} from the response, and only then does the flow continue to the actual submission. Put a condition on the connection so the flow only continues when a token actually came back. If the advertiser requires signed requests, use the Signature setting on the HTTP node rather than building the signature yourself. When the advertiser does not answer immediately Plenty of advertisers accept the lead, then take a few seconds to decide anything useful. There are two ways to handle it. Poll them. Add a Wait node, then an HTTP node that asks for the status, then conditions on the outgoing connections: A final positive state continues to the Set node and the End. A final negative state goes to an End marked failed. Anything else loops back through a Breaker and another Wait. The Breaker caps the number of attempts, so the flow cannot poll forever. Match the “still waiting” branch with does not match against the known final states, so a state you have never seen lands in the retry loop instead of falling through. Let them call you. If the advertiser sends a callback, use a Webhook node. The flow pauses there and continues when the call arrives, which is cheaper than polling and usually faster. A webhook can deliver several kinds of event, so branch on what arrived. Conditions on the connections leaving the node read the values from the callback, and each kind of event goes its own way. Give the webhook its own retry path as well, through a Wait and a Breaker, so a callback that never comes does not leave the flow hanging until the timeout. Remember that the customer is often sitting on a loading screen while all of this happens. See Limits and timeouts. More than one request Some advertisers need a sequence: submit the lead, ask for the offer, accept the offer, then ask again to confirm it was accepted. Each of those is another HTTP node, chained with conditions between them. Two things keep this manageable: Store the ID from the first response into {external_id} immediately, because every later request needs it in the URL. Give each step its own condition. If you only check the last response, you will not know which step actually failed. Once the sequence is more than three requests long, it is worth asking the advertiser whether there is a simpler endpoint. Often there is. Verification Some advertisers confirm the lead with a code sent to the customer by SMS. This runs as its own flow with its own Start node. The pattern is: In the Post flow, store whatever identifies the pending verification, for example the token ID and the token code returned by the advertiser. In the verification flow, send those back together with the code the customer typed, available as {code}. On success, store {redirect_url} and end. The two flows are connected by the values stored in the first one, not by a line on the canvas. Ending the flow Every path should reach an End node, and the End node decides how the lead is recorded. Success means the advertiser took the lead. Failed means they did not. A rejection is a normal outcome, not an error. Give it a reason so it shows up usefully in reporting, rather than landing in Error along with genuine breakages. See Reject reason. Common mistakes Treating any 2xx status as acceptance. Not storing {external_id}, so postbacks can never be matched. Not storing {price} in an integration meant for an auction, so it cannot bid. Rebuilding the logic for each channel instead of duplicating the integration and changing the credentials. Translating values inside the HTTP body instead of in Modify Field, which makes a wrong value impossible to trace. Connecting the Ping and Post flows. A polling loop with no Breaker. Leaving a branch without an End node, so the lead ends up in neither result. #### Connection Creator in Structures A Structure scenario runs inside the lead flow itself, while the customer is still filling in the form. It can shape the data, fill in what is missing, or stop the lead before it is finalised. You find these under Tools / Validation. There are three purposes. All three are built the same way, with an HTTP node to call the external service, a Set node to store the result, and conditions on the connections to branch on the response. What differs is how they end. Validation checks a value against an external service and can reject the lead. Modify fills a field with a value pulled from somewhere else. Autosuggest offers suggestions while the customer types. The customer is waiting Structure scenarios always run instantly. The customer is sitting in front of the form while the flow executes, so the whole thing has to finish inside the synchronous limit, not just one node. Keep the HTTP timeout short and do not chain lookups you do not need. See Limits and timeouts. What decides whether the lead is rejected Not the response. Not the branch. The success setting on the End node. An End node set to failed rejects the lead. An End node set to success lets it through, whatever the branch was about. The title of an End node has no effect. You can call it Invalid and still let the lead through, and that is exactly what a Modify scenario does: finding no company number is a valid outcome, it just means the field stays empty. Read the success setting, not the label. Two rules: Only the branch that genuinely means “this value is wrong” should end in failed. An outage or an unexpected response must never end in failed. Otherwise every hiccup on the other side starts rejecting real customers. Validation Ask an external service whether a value the customer entered is valid, and reject the lead if it is not. Phone numbers are the usual case, since bad numbers are the biggest single source of rejected leads. The shape: Start node, type Structure. HTTP node, usually a GET, sending the field value to the validation endpoint, for example phone={phone}. Three connections out of the HTTP node, each with its own condition: Valid. {status} equals 200 and {parsedBody.valid} equals true. Ends in success. Invalid. {parsedBody.valid} equals false. Ends in failed. This is the only branch that rejects. Outage. {status} matches \b[45]\d{2}\b. Ends in success, because a broken service is not a bad lead. All conditions on one connection must be true for it to be followed. That is why the valid branch checks two things: that the call succeeded and that the service said yes. Checking only the body means an error response with no valid field can slip through. Match the outage branch with a pattern rather than listing individual status codes. Anything unexpected then lands there instead of falling through somewhere it should not. Modify Take something the customer already gave you, look it up externally, and fill a different field with the answer. A company registration number becomes a company name and address. The shape is the same as validation, with one difference: every branch ends in success. Enrichment must not reject a lead just because the lookup came back empty. An empty result is an answer, not a failure. Use failed only when a missing value is by itself a genuine reason to turn the lead away. The shape: Start node, type Structure. HTTP node calling the lookup endpoint, for example companyNumber={company_number}. Three connections: Found. {status} equals 200 and {parsedBody.name} is not empty. A Set node writes {company_name} = {parsedBody.name}, then End, success. Not found. {status} equals 200 and {parsedBody.name} is empty. A Set node with nothing in it, so the field stays blank, then End, success. Outage. The 4xx or 5xx pattern. End, success. Handle both real outcomes explicitly. Do not leave the negative case to a fallback, because then you cannot tell “we looked and found nothing” apart from “we never got an answer”. When the API needs something the customer did not give you Sometimes the lookup needs an input that is not a field on the form. The form collects a full name in one field, and the registry expects a first name and a last name separately. Add a Modify Field node before the HTTP node. It reads the field you have, transforms it, and writes the result into new fields the request can use. If you then add a guard on the imported field, such as a do-not-send, be careful with the condition. It has to compare against the live value from the response, written in braces as {parsedBody.name}. Typed without braces it is just a literal string, it can never match, and the guard silently does nothing. Autosuggest While the customer types, call a suggestion service and hand back a list for the form to show as a dropdown. This is the simplest of the three. No branching, no rejection: Start node, type Structure. HTTP node, usually a POST, sending the partial input, for example fieldType: COMPANY_NAME and values.COMPANY_NAME: {company_name}. Set node storing the whole list, for example {autocomplete_result} = {parsedBody.suggestions}. End node, success. The form takes it from there: it renders the list and lets the customer pick one. Because this runs on every keystroke, the timeout matters more here than anywhere else. A slow suggestion service does not just delay the answer, it makes the field feel broken. #### Connection Creator in Tracking Connection Creator is not only for delivering leads. It also handles what happens to a conversion after the lead was delivered: confirming it, updating it, or deciding what it is worth. There are two directions, and the difference is who makes the call. S2S postback : the advertiser calls PalDock. Tracking API : PalDock calls out. Both use the same editor. This page is about what you build inside it. When each one fires, and how an incoming S2S postback is matched to a lead, is covered on those two pages. S2S postback The scenario runs when an advertiser reports the outcome of a conversion: approved or rejected, the sale value, the approved loan amount. The simple case needs no scenario at all. The postback is received and stored on its own. You only build a flow when something more has to happen. The useful case is branching on what arrived. Send another request when the postback comes in incomplete, or work out the commission from a value the advertiser reported. One thing to set up first: if a postback has any steps configured, the advertiser must send a Postback ID with the call. Without it the postback is still received, but your flow never runs. Example: commission tiers based on the loan amount The advertiser sends {value}, the approved principal. The scenario reads it and sets {commission}: {value} under 500 : commission 10 USD {value} from 500 to 800 : commission 17 USD {value} 800 and above : commission 23 USD In the editor: One Start node Several connections leaving it, each with a condition comparing {value} against a threshold, using is less than, is greater than or equals and so on. See Connections with Conditions. One Set node per branch, writing the amount into {commission}. The pattern to remember: conditions live on the connections leaving the Start node, and every branch ends in a Set node that writes the final value. Building on top of it Once {commission} is set, you can reference it in a commission formula, for example {commission}+10 for a VIP group. The base logic then lives in one scenario, and specific partner groups get an uplift on top without duplicating it. See Commission amount. Tracking API Here PalDock decides when to call. Nothing is arriving, so the scenario controls when to check, how often to try again, and when to give up. Polling for a result The most common use. Ask the advertiser’s API what happened to a lead, and once it reaches a final state, update the transaction and read the value or commission out of the response. The usual shape: Start node Wait node, for example 12 hours, to give the advertiser time to process the lead before the first check. Modify Field node if the request needs authentication built first, such as Base64-encoding credentials for a Basic auth header. HTTP node, a GET to the advertiser’s status endpoint, using the advertiser’s own ID for the lead. Conditions on the connections leaving the HTTP node, matching the status field in the response: A final rejected state : Set node writing {result} = rejected, then End. A final approved state : Set node writing {result} = approved, and optionally {commission} straight from the response, then End. Anything else, meaning still pending : into the retry loop. The retry loop is a Breaker node plus a Wait node, looping back into the same HTTP node. The Breaker caps how many times it may repeat, for example six. Match the pending branch with does not match against the known final states, rather than listing every pending state the advertiser might invent. New states then land in the retry loop instead of being ignored. When the Breaker limit is reached, the flow stops without a final state. Nothing is written and nothing is retried. Those leads end up neither approved nor rejected, so decide separately what to do with them. Set the wait and the repetition count so the total window covers how long the advertiser realistically takes. Wait, check, branch, retry with a cap. That is the backbone of almost every polling integration. Sending data to a partner The same mechanism in reverse: pushing data out to a specific advertiser or partner. From their side it looks like a postback arriving. From yours it is still a Tracking API, because PalDock decides when to call and what to send. Affiliates can create their own Tracking API postback. They become its owner and see it in their administration, and only their own data is ever sent to it. That restriction is locked and they cannot change it. As an admin you can also create a postback and assign an owner to it. The owner then sees it in their administration, exactly as if they had made it themselves. The difference is that you are not bound by the same restriction: you can assign an affiliate as the owner and still send them data covering everyone, not only their own. Sending data to ad systems The same again, for forwarding conversions and events into advertising platforms. It can be set globally for the whole workspace, or scoped to individual accounts or campaigns. Both use the same conditions as everywhere else in PalDock, such as matching on result or comparing a value. #### Connections with Conditions A connection is the arrow between two nodes. It decides what runs next. Left empty, it is always followed. Given a condition, it is followed only when that condition is met. How a condition is built Three parts: Value, what you are checking. Operator, how it should be compared. See Condition Operators and Field value. Output, what you are comparing it against. Some operators need two, such as Is between. Others need none, such as Is true. You can also give the condition a Title and Subtitle. These have no effect on the flow, they are labels shown on the arrow in the editor. Use them, because a canvas of unlabelled arrows is unreadable a month later. Picking a value Both Value and Output have a picker, so you do not have to remember names. It offers four groups: Form Fields, the fields of the structure the lead came from. Keys, the tokens, endpoints and parameters the integration uses. System Parameters, values PalDock fills in itself. Previous Steps, everything produced earlier in the flow, including the parsed response body and the query of a previous request. There is no separate Source setting. Where the value comes from is decided by what you pick, so a field from a response body is picked under Previous Steps rather than selected as “body” somewhere. You can also type a value in directly, which is how you compare against a fixed string or number. Example: Value: {parsedBody.status} Operator: Equals Output: ok This connection is followed when the response body contains a status field set to ok. Several conditions on one connection All of them must be true. There is no way to make them alternatives. {status} Equals 200 {parsedBody.valid} Equals true This is followed only when the call succeeded and the service said the value is valid. Checking only the body is a common mistake, because an error response usually has no valid field at all, and the connection then behaves in ways you did not intend. If you need alternatives, use two connections leading to the same node, each with its own condition. Several connections from one node Every connection whose condition is met is followed. That is how the flow branches: one node leads to three others, and the response decides which paths continue. Two things follow from this: Make the conditions mutually exclusive, unless you want more than one branch to run. Two conditions that can both be true will both fire. Cover everything. If no connection matches, the flow stops there. Nothing is written, nothing is retried, and the run simply ends at that node. The safest way to cover everything is to match the known outcomes explicitly and catch the rest with a negative match against them, rather than trying to list every value the other side might return. Branching on a response An advertiser returns a status and you want three outcomes: Rejected: {parsedBody.state} Regex match DEN|CAN Approved: {parsedBody.state} Equals APPROVED Pending: {parsedBody.state} Regex not match DEN|CAN|APPROVED Anything new the advertiser starts returning lands in Pending, which is where you want it, rather than falling out of the flow. Common mistakes Braces in the wrong place. Value takes a reference. Output takes what you compare against. Writing a field path into Output as plain text makes it a literal string that can never match. Relying on the status code alone. Most advertisers return a rejection with a perfectly normal 200. Leaving no path for the unexpected, so runs quietly end in the middle of the flow. Overlapping conditions on branches that were meant to be alternatives. #### Conversion -> Commission -> Transaction Three words come up constantly in PalDock, and everything else makes more sense once they are clear. A conversion is something that happened. A commission is a rule about what it is worth. A transaction is the money that came out of it. Conversion A conversion is a recorded event with no money attached. It reaches PalDock in one of two ways: Created by PalDock: clicks, leads, and sends. These happen because somebody clicked a link or submitted a form. Received through tracking: prospects, sales, and any custom type you define. These are reported by the advertiser, through a pixel, a postback, the Tracking API, or a manual import. On its own a conversion is a performance metric. It appears in reports, it counts towards your click and lead numbers, and it pays nobody. See Conversion type. Commission A commission is the rule that turns a conversion into a payout. It decides: Which conversions it applies to, by offer, advertiser, conversion type, source, and channel. How much is paid, to your partner and by your advertiser. What kind of transaction is created. See Transaction type. Without a matching commission, nothing is paid. The conversion is still recorded, it simply produces no transaction. See How PalDock picks a commission. Transaction A transaction is a conversion with a payout and a result: pending, approved, or rejected. It has two sides, what you pay the affiliate and what the advertiser pays you, and they are synchronised. Approving one approves the other, so the two can never disagree. How it fits together A visitor clicks an affiliate link, which creates a click. They fill in a form, which creates a lead. Days later the advertiser confirms the order, which creates a sale. Three conversions, one journey. Your commission says a sale on this offer is worth 40 to the affiliate and 55 from the advertiser, so the sale produces a transaction. The click and the lead stay as they are, counted in reports and paid for by nobody, unless you have commissions for them too. When there is no transaction A conversion exists but no payout appeared. The usual reasons: No commission matches that conversion type. The commission is inactive or outside its active period. The recurrence limit was reached. The conversion was deduplicated on the advertiser’s external ID. The conversion log tells you which one it was. See Tracking and Conversion Logs. #### Conversion IDs explained PalDock gives every step of the journey its own ID. Sending the right one is what decides whether a tracking request creates a new record, updates the right one, or fails to match anything. The objects Origins are clicks and leads. Every journey starts with one. Sends are the individual deliveries of a lead to a channel in a Pingtree. One lead can have many sends. Conversions are sales and prospects, whether they arrived through tracking or were created by a commission. Transactions are conversions that a commission applied to, so they carry a payout amount and a result. The IDs Origin ID: the click or the lead. Created by PalDock at the very start and passed to the advertiser. This is the ID you use to attribute anything back to the affiliate. Send ID: one delivery of a lead to one channel. Use it when you need to talk about a specific channel in a Pingtree, not about the lead as a whole. Conversion ID: one sale or prospect. Created when the conversion is recorded. Transaction ID: one transaction. A conversion can have several if several commissions apply. External ID: the advertiser’s own ID for the order. You do not create it, the advertiser sends it. See Deduplication based on advertiser’s ID. Affiliate CID: the affiliate’s own ID for the conversion, sent as affcid. PalDock stores it and sends it back so the affiliate can match records on their side. Process ID: not an object ID. It identifies one asynchronous API call while it is being processed. Which one to send Creating a conversion, by pixel, postback, or Tracking API: Send the Origin ID, or the Advertiser ID together with the External ID. Either pair is enough to attribute the conversion. Sending both is the safest option and we recommend it. Updating a conversion: Send the External ID with the Advertiser ID. Or send the Conversion ID when you have it. It is unambiguous. The Origin ID alone is not enough once more than one conversion exists under the same origin, because PalDock cannot tell which of them you mean. Pingtree: why the Origin ID is not enough In a Pingtree, one lead is sent to several channels. Every one of those sends carries the same Origin ID, because they all come from the same lead. That has a direct consequence for tracking: The advertiser receives the Origin ID and sends it back with the conversion. PalDock cannot tell which send that conversion belongs to, because several sends share that ID. Two advertisers in the same Pingtree can therefore report against the same Origin ID. What to use instead: Advertiser ID together with External ID is the reliable pairing in a Pingtree. The advertiser is unique, their own order ID is unique on their side, and the combination points at exactly one conversion. Send ID identifies one delivery to one channel. Pass it to the advertiser in the integration and ask for it back if you want the conversion tied to that exact send. Origin ID on its own is fine for a single-channel offer, and unreliable as soon as a Pingtree is involved. If you run Pingtrees, agree with every advertiser that they always return their External ID. Without it you cannot separate their conversions from another channel’s. Where you find them Click and lead log: Origin ID Integration log: Origin ID, Send ID Conversion log: Origin ID, Send ID, Conversion ID, Transaction ID Transaction report: Origin ID, Send ID, Conversion ID, Transaction ID In API responses: A completed call returns the Origin ID and, for a Pingtree, the Send ID. A call that is still running returns the Process ID, and the object IDs once it finishes. Pixel and postback responses return the Conversion ID and the Origin ID. Store what you get. The Origin ID is the one you will need most often later. #### Conversion type Conversion types are the events PalDock records. Every conversion has exactly one type, and it decides which commissions can apply and which pixel is used. See table below to know which types are created by which event. [table id=7 /] Click: a visitor followed an affiliate link. Lead: a form was submitted through an iFrame or the API. Send: one delivery of a lead to one channel in a Pingtree. A lead can have several. View: an impression. Prospect and Sale: reported by the advertiser through tracking. Types created by PalDock cannot be created by a tracking request. Tracking can only update them, and an update that carries a different type creates a conversion of that type instead. See Tracking processing. Custom conversion types When the six built-in types are not enough, create your own in Workspace Settings, Tracking, Conversion types and pixels. Custom types behave like sale and prospect: they are reported through tracking and can be paid on. Each type, custom ones included, comes with its own tracking pixel, in an advertiser version and an affiliate version. Rules that apply to every type Transaction type does not have to match. A commission can create a transaction of a different type, and PalDock will create the conversion for it. See Transaction type. type is required when creating a conversion, and must match a type that is allowed on that channel. Click, lead, and send cannot carry an external ID. It belongs to the advertiser’s order, which those types do not represent. A type can have several commissions. Send the Commission ID to say which one applies, otherwise the first one in the order is used. #### Currency Currently, each offer can have only one assigned currency. This currency is also used for all connected commissions. The offer currency is the real one Everything that happens on the offer happens in its currency. The commission is defined in it, the transaction is created in it, the partner’s balance grows in it, and the invoice is issued in it. Nothing along that path is converted, so the amount a partner sees on the invoice is the amount the commission said. A partner promoting three offers in three currencies has three balances and is invoiced in all three. The workspace currency is for reading, not for paying Reports would be unreadable if every row carried its own currency, so PalDock converts values into the default currency of the workspace and shows one total. The default currency is set in Workspace Settings. That conversion exists only so numbers can be added up and compared. It does not change what anyone owes or is owed: In reports you see converted values, so revenue across all offers is one number in one currency. In transactions, balances and invoices you see the offer currency, because that is what gets paid. #### Custom keys Sensitive values never live in scenarios or nodes. Not in a node parameter, not hardcoded in a mapping, not in a comment. Everything goes into the Secrets table in the integration’s General section. This includes endpoints. An endpoint is not sensitive in the common sense, but it is environment-specific, and treating it as a secret is what makes the test/production toggle work. The scenario references the secret slot. It never contains the value. Why the names are fixed The library maps blueprints onto global fields using a fixed set of secret names. That’s what delivers the core promise: a user adds a blueprint to their workspace, maps nothing, fills in their own secrets, flips one toggle, and it runs. The moment one blueprint uses api_key instead of token, that promise breaks for that blueprint and the user is back to manual mapping. The naming isn’t a style preference, it’s the library’s API. The allowed list is closed. custom_* is the only free space. Validate blueprint secret names automatically against the allowed list at creation time. If a value is recurring across providers (an auth host, a tenant ID, an account/subaccount identifier), it doesn’t belong in custom_*, but it belongs in the fixed list. custom_* is for genuinely provider-specific one-offs, and every recurring value that lands there fragments into five different names across five blueprints. The slots endpoint = root API domain. The path is appended in the scenario, so store https://api.provider.com/, not https://api.provider.com/v2/leads. endpoint_auth = token/authorization host, when it differs from the API host. Common with larger providers (auth.provider.com vs api.provider.com). If auth lives on the same host as the API, this stays empty and the path is appended in the scenario like any other. endpoint_secondary = any secondary endpoint URL token = primary token / API key / client ID. Whatever the provider considers the main identifying credential. token_secondary = second token / secret / client secret. For signed requests use sign_secret and sign_keyid instead. partner_id = partner / broker / channel identifier. Not a signing key ID – see sign_keyid. sign_secret = secret used to compute a request signature (HMAC-SHA256, MD5, …). Not sent in the request – only the digest derived from it is. sign_keyid = public identifier of the signing key, sent alongside the signature so the provider knows which secret to verify against. Depending on the provider this appears as key ID, access key ID, keyId in the Signature header, client ID in a signed request, or an app/API ID paired with the secret. username = basic auth login. password = basic auth password. price = lead price (only if it is static) redirect_url = return URL. (if it is static) custom_* = anything else, free suffix. Use sparingly, see above. Every field has a checkbox for a paired test-environment value. Switching between environments is one toggle at the integration level. You dont need to duplicate an integration for sandbox, and encode the environment into the name (token_test, endpoint_sandbox). Which slot for which auth type The slot names are generic on purpose. What goes in token is decided by the blueprint’s auth mode, not by what the provider happens to call it in their docs. Static API key (header or query param) token – the key endpoint – API root Provider calls it api_key, X-Api-Key, apikey, access_key? Doesn’t matter. It goes in token. Basic auth (base64) username – login password – password endpoint – API root The base64 encoding happens in the blueprint, not in the stored value. Store the two halves separately and let the HTTP module (or an explicit base64(username + ":" + password) step) build the header. Do not store a pre-encoded dGVzdDpwYXNz blob in token. It can’t be rotated one half at a time, it can’t be paired cleanly with a test value, it’s unreadable in the UI, and nobody six months from now will know which half changed. Bearer token, long-lived (no refresh) token – the bearer value endpoint – API root The blueprint prepends Bearer . Don’t store the prefix in the secret – some providers use Token , JWT , or nothing at all, and the prefix is the blueprint’s business. OAuth2 — client credentials token – client ID token_secondary – client secret endpoint_auth – token host, if it differs from the API host endpoint – API root Scope, audience, grant type and the token path are blueprint configuration, not secrets. They’re the same for every user of that provider. Only put a scope in custom_scope if it genuinely varies per account. OAuth2 — authorization code / refresh token token – client ID token_secondary – client secret endpoint_auth – auth host redirect_url – callback URL registered with the provider The refresh token is not a secret in this sense. It’s runtime state – it rotates, sometimes on every use. See What must not go into Secrets. HMAC / signed requests token – API key or partner identifier sent in the clear token_sign – the signing key endpoint – API root The signature algorithm, the field order, and what exactly gets hashed are all blueprint logic. They’re identical for every user of the provider, so they don’t belong in Secrets. Basic auth + separate signing (common in insurance / energy feeds) username, password – transport-level auth token_sign – payload signing key partner_id – the identifier the provider uses to attribute the lead What must not go into Secrets Secrets is configuration. It is not state. An access token obtained at runtime does not get written back into the Secrets table. Neither does a rotating refresh token, a session ID, or a cached signature. Writing runtime tokens back buys you: Race conditions. Two parallel scenario runs refresh at the same time and overwrite each other. One of them then holds a token the provider has already invalidated. Environment bleed. A cached token from sandbox survives the test/production toggle and gets sent to the live endpoint, or the other way around. A useless audit log. The Secrets change history fills with refresh writes, and you can no longer see when a human actually changed a credential. Broken rotation. When someone rotates the client secret, you can’t tell which stored value is the credential and which is derived from it. Instead: Keep a separate token cache at the integration level, keyed by integration_id + environment. Store the expiry, refresh proactively before it, and refresh reactively on a 401. The cache is invisible to the user and clears when credentials change or the environment toggle flips. #### Dashboard The Dashboard is the first screen after logging in. It is a summary of the workspace plus the handful of actions you take most often, so the everyday routine does not require opening a report at all. What you see depends on who you are. For admins The numbers The row of Highlights at the top shows your key metrics for the selected period. This is also the place where Highlights are added and removed, and the set you choose applies wherever they appear. Below them, a short table gives the last few days and the most recent conversions. Enough to notice that something stopped, without going into reports. Top offers and affiliates Your best performing offers and partners, with the option to pin the offers you watch most so they stay at the top. Onboarding New affiliates and advertisers waiting for approval appear here, and you can grant them access to the workspace or to specific offers without leaving the page. Whether they wait for you at all is a workspace setting. See Settings. Payouts Affiliate payout requests and advertiser invoices are approved from the Dashboard, next to the numbers they came from. For affiliates Their results for the selected period, in the same Highlights format. Tracking links. An affiliate generates a link for any offer they have access to directly from the Dashboard, without going through the offer. Payout breakdown by result, so they can see what was approved, what is still pending, and which transactions each amount came from. The period Everything on the Dashboard follows the date range you pick, and it respects the result type filter and the reporting time basis the same way reports do. A Dashboard that disagrees with a report is almost always one of those three set differently. #### Data feeds A data feed holds product information such as names, logos, prices or availability, and PalDock can match a lead against it. API responses include a feed_id, which tells you which feed the data for that lead comes from. The response can also override individual values from the feed for one specific lead. This matters where the offer is standardised but the price is not, for example a mortgage where an individual customer is quoted their own interest rate. The External Final Page uses the same feed to match products, which is the most common reason to set one up. #### Deduplication based on advertiser’s ID When the same conversion reaches PalDock more than once, whether by mistake or because you run several tracking methods at once, deduplication keeps a single record of it. It works through the external_id parameter, the advertiser’s own ID for the order. See Tracking parameters. How the duplicate is recognised A conversion is treated as a duplicate when a valid conversion already exists with the same: External ID Advertiser Conversion type If three requests arrive with the same order ID, one conversion is recorded and one transaction is created, not three. Because the conversion type is part of the match, a prospect and a sale with the same external ID both pass. They are different events on the same order. What happens to the duplicate The request is accepted and logged, so nothing is silently lost. The conversion is marked as a duplicate and stays invalid, so no commission runs on it and no transaction is created. You can see it in the conversion log with the duplicate status. When the Commission ID changes the outcome If the request carries a Commission ID, deduplication is judged per commission instead of per conversion. Without a Commission ID: the second conversion is refused whichever commission would apply. With a Commission ID: the second conversion is refused only if that commission already created a transaction for this external ID. Another commission can still be applied. Why you should always send external id Even when you are not worried about duplicates, the external ID is what lets PalDock recognise an order later. Update requests need it. Without an external ID or a conversion ID, PalDock cannot tell which conversion the advertiser means, so results are never updated. See Recurrence type. Recurrence limits are counted per external ID, so repeat orders from the same customer are paid correctly. If the first request arrives without one and a later request for the same conversion brings it, PalDock saves it onto the conversion. An external ID that is already stored is never overwritten. There is no way to add it afterwards by hand, so ask the advertiser to send it from the start. Deduplication or recurrence Deduplication refuses the duplicate conversion itself, before any commission runs. It needs the external ID. Recurrence limits how many transactions one commission may create. It works even with no external ID. #### Deep link PalDock supports deep linking, allowing affiliates to send traffic directly to specific product or landing pages instead of a generic homepage. Each deep link automatically includes the affiliate tracking parameters, ensuring clicks and conversions are correctly attributed. This gives affiliates more flexibility in campaigns, for example linking users straight to a loan application form or a detailed product page while maintaining full tracking and reporting in PalDock. How to build one Add the destination parameter to the affiliate link, holding the URL you want the visitor to land on. The value must be URL-encoded, so https://www.example.com/product/123 becomes https%3A%2F%2Fwww.example.com%2Fproduct%2F123. Without encoding, everything after the first & in the destination is read as a parameter of the affiliate link instead of part of the destination, and the visitor lands on the wrong page. It has to stay on the advertiser’s domain The destination points to another page within the same advertiser domain, not anywhere on the internet. This is a restriction on purpose: a link that could redirect anywhere would be an open redirect on your domain, and would be abused. If a partner needs to land visitors somewhere the advertiser does not host, that is a different offer, not a deep link. Where it makes sense Shops, where the partner reviews one product and wants the visitor on that product’s page. Comparison sites, where each row leads to the thing that row is about. Multi-product advertisers, where the homepage would make the visitor choose again. Where the advertiser has one landing page and one product, a deep link adds nothing. #### Display amount Display amount lets you replace a complex commission formula with a clear, user-friendly label. This makes it easier for you and your partners to quickly understand the payout logic without exposing the underlying calculation. For example, if your formula is 0.05 * {value} to pay partners 5% of the value, you can simply set the Display amount to “5%” instead of showing the full formula. If the Display amount does not provide enough context, you might also want to check out the Commission Detail feature, which allows you to add a short descriptive note that appears in the commission table. #### do-not-send The do-not-send operation removes a value instead of changing it. The field is emptied, and with the right setting on the request, it is left out altogether. Use it when an empty value is worse than no value, and when something in your data should never reach the other side. How it works There is no parameter. The condition does all the work. Condition: is empty → the field is dropped Condition: equals test → dropped only when the value is exactly "test" Condition: always → the field is never sent When the condition is not met, the field carries on as normal with its value untouched. It works together with the request settings do-not-send clears the value. Whether the field then disappears from the request or arrives as an empty one is decided on the HTTP request node, by the Skip field when setting. If you want the field genuinely gone, set that to skip on null. Without it the advertiser may receive the key with nothing in it, which for some APIs is the very thing you were trying to avoid. This is worth checking before you rely on the operation. Two integrations built the same way can behave differently here, purely because of a setting on the request rather than on the field. When to reach for it Empty optional fields. Some APIs are stricter about an empty value than about a missing one, and will reject a request carrying a blank field they never needed. Test data. Keeping a placeholder from reaching a production endpoint. Values that are only sometimes relevant. A company number that applies to the self-employed and to nobody else. Send it when it means something, drop it when it does not. Careful with required fields Dropping a field the advertiser requires produces a rejection, and their error message will usually name the field rather than explain that it was missing. Before setting this up, check their documentation for what is genuinely mandatory. Where a field is required but your value is empty, set a placeholder instead of dropping it. Finding out what was dropped A suppressed field leaves no trace in the payload, so a request that looks wrong gives you nothing to work from. The run log shows what the node received and returned, and {request_body} on the HTTP node shows what actually went out. Compare the two and the missing field is obvious. See HTTP request. #### Editor The Editor is the visual tool where you build a scenario. Nodes appear as dots on a canvas. You drag them, connect them with lines, and configure what each one does. Nodes A node is one action: send a request, change a value, wait, finish. There are two kinds. Built-in nodes are the core elements provided by PalDock, such as Start, Modify or HTTP. They work the same in every workspace. External nodes represent an outside service or API and are what connects PalDock to a third-party platform. Click any node to open its configuration panel, where you define its inputs, outputs and rules. Adding a node Click the plus on the canvas and a panel opens with everything you can add. Type in the search box to find a node by name, or browse the groups: Flow control decides when and whether things happen: Wait, Breaker. Data operations change the data: Modify, Set. Connections talk to the outside world: HTTP, Webhook. Composition builds the scenario itself: Start, End, SubScenario, Mirror. The tabs along the top are only a filter. The first one shows the nodes you reach for most often, and the rest narrow the list to one group. Nothing is hidden, so if you know the name, searching is quicker than browsing. See List of nodes for what each one does. The Start node Every scenario begins with a Start node. Its type follows the context the scenario belongs to: Integration, Structure or Tracking. See Where Connection Creator is used. A scenario can have more than one Start node when it serves separate paths that must not touch, which is how PING and POST flows are built in a pingtree. See How to integrate anything. Connecting nodes Nodes are joined by lines. A connection defines the order in which nodes run. Connections can branch. One node can lead to several others, so the flow takes a different path depending on a condition, for example routing leads to different integrations based on a validation result. Every connection can carry a condition that decides whether the flow continues along it. If the condition is not met, that line is not followed, while other lines from the same node still can be. See Connections with Conditions. Choosing a value Almost every node asks you for a value: which field to send, what to compare against, where to store a result. You never have to remember names. Open the picker and take what you need from what the scenario has at that point. It offers four groups: Form fields are the fields of the structure the lead came from, such as first_name or email. They are grouped the way the structure is, so related fields sit together. Keys are the tokens, endpoints and parameters this integration uses. System parameters are the values PalDock fills in itself, covering the conversion, the commission, the offer, the advertiser, the affiliate, the integration and the time. Previous steps is everything the earlier nodes produced, including a path into a response body. The picked value appears as a tag in the field, and underneath it is stored in braces, such as {email} or {external_id}. You can type instead of picking, and mix the two freely, so Bearer {token} works as one value. Only what was produced before the current node is available, because data travels forward and never back. If you need a value of your own, store it with a Set node and reference it by name afterwards. See page parameters for what PalDock provides. Turning a node off A node can be disabled without deleting it. A disabled node is skipped and the flow does not continue past it. This is the safe way to take one branch out of a live scenario while you work on it. Reusing a node If the same request or configuration is needed in several places, do not copy it. Use a Mirror node, which inherits all settings from its master and updates automatically whenever the master changes. Typical workflow Start. Every scenario begins with a Start node. Add nodes. Drag in built-in actions or external integrations. Connect. Join them to define the order, and add conditions where the flow should branch. Configure. Open each node and set its parameters, such as endpoints, credentials, field mapping and rules. Run and test. Execute the scenario and check what happened in the log. Checking what happened Every run stores the input and output of each node. Open the run and follow it node by node. You will see the exact data each node received and returned, which is where you start whenever something does not work. See Logs. #### Embeddable form Users with access to a specific Offer can view its details together with allowed propagation options (Link, iFrame, API). Embeddable forms allow affiliates to embed a lead form directly on their website. Visitors can fill in the form to convert into a lead, which is then sent to PalDock for processing. The affiliate can copy the embed code from the Offer Preview section and customize the form’s style to match their website. Admins define the form structure in Form Structures and assign them to offers. In the Design section, forms can be styled according to tenant needs. Form Parameters The most common parameters used in PalDock are: affcid – a custom click identifier provided by the affiliate. affs1 to affs10 – custom fields where affiliates can pass their own IDs or values for tracking and reporting. affiliateID – identifier of the affiliate sending traffic, which can rewrite the original owner of the form. The AffiliateID rewrite feature must be enabled. external_redirect_url – an alternative URL where the user should be redirected after form submission. The External Final Page feature must be enabled. test – marks the lead as a test so it will not be processed as a standard lead. Parameters can be passed either in the URL, which takes precedence, or in the form body. Form Features Pre-filling fields – the form can be prefilled by passing data_fieldname=value, where the field name matches a field in the offer’s form structure. The Pre-filling fields feature must be enabled. Auto-submit – the form can be set to submit automatically by adding system_submit=true. If some fields are missing, validation triggers an error and the user is asked to complete them. The Auto submit feature must be enabled. The form and the page around it The form runs in an iframe on the partner’s site, which has two consequences worth knowing before you go live: The form cannot read the page it sits on. URL parameters, cookies and referrer belong to the partner’s page, not to the iframe. Anything the form should know has to be passed into the embed URL, or collected afterwards with the update pixel. Cookies inside the iframe are third-party cookies. That is why the redirect after submission goes to a page on your own domain rather than staying inside the iframe. See Pingtree Distribution. Tracking in DataLayer The form pushes events to the DataLayer so PalDock or any other tracking scripts can pick them up, for example started when the visitor begins filling the form and lead when it is submitted. On submission the form also pushes the conversion ID, so tracking scripts can use it to update the lead with additional information from cookies or URL parameters. See Update pixel. #### End trigger The End node marks how a flow finished. Every path should reach one. There are two settings you can choose: Success, the other side accepted the request. Reject, the other side turned it down. Error is what happens without an End node Error is not a setting. It is where a flow lands when it never reached an End node at all, whether because something broke, or because no connection matched and the run simply stopped. That is why marking every path explicitly matters. A rejection is a normal outcome, and if it is left to fall into Error, it stops looking like a business result and starts looking like a fault. Error should stay reserved for things that are actually broken, so it remains useful in logs and worth being notified about. Check every branch of your flow leads somewhere. A branch that trails off without an End node is the most common way leads end up in Error for no reason. Give a rejection a reason A rejection on its own tells you the lead was not taken. A reason tells you why, and that is what shows up in reports, aggregated across all your integrations. Whatever the advertiser sends back can be mapped onto your own set of reasons, or onto the standard ones, so that rejections from different advertisers are comparable. See Reject reason. #### Export Any table in PalDock can be exported for further work in Excel, Google Sheets, or a BI tool. Click the Export button in the table header, set the options below, and press Download. File format CSV, the default XLSX Delimiter For CSV you choose which character separates the fields: Comma Semicolon Tab Which one you need depends on what will open the file. Excel in a European locale expects the semicolon, most other tools expect the comma. Columns All available: every column the dataset has, including the ones hidden in your current view. Only displayed: the columns currently switched on in the table. Because the export can include hidden columns, you do not have to widen the table just to get a field out of it. See Advanced columns. Rows All available: everything matching your current filters, not just the page you are on. Only displayed: the rows on the current page. Only selected: the rows you ticked in the table. This option appears once at least one row is selected. See Show rows in chart. What ends up in the file Your filters are applied. The export is the table you are looking at, not the raw dataset. That includes the result type filter and the reporting time basis, so an export made on approved transactions contains only approved transactions. Amounts carry their currency. Whenever a column holds an amount, the matching currency is exported next to it, so nothing has to be guessed from the workspace default. Partners export what they can see. An affiliate or an advertiser exporting the same table gets their own rows and their own columns, with the same restrictions that apply on screen. #### External Final Page The External Final Page feature lets partners, or you yourself, replace the internal PalDock Final Page with their own page. Use it to keep control of the branding, to show PalDock results alongside your own offers, or to build the results into a comparison site. It works with both API and iFrame submissions. Admins decide whether to enable it for API only, iFrame only, or both. The flow, once Whatever else you configure, this part never changes: A lead is created. The response contains process_id and url. url always points to the Internal Final Page, https://portal.paldock.com/{tenant}/processes/{process_id}. It never points at your page. The customer goes there. From an iframe this happens automatically, from the API your frontend does it. The Internal Final Page redirects onward to your external page. Your page reads the result and renders it. Everything below only changes when step 4 happens and how you get the data in step 5. What you configure Six settings on the offer, plus three parameters on the request. They are independent, and confusing them is the usual reason an integration behaves unexpectedly. On the offer: External Final Page – turns the feature on, and for which submission methods. Default External Final Page – the URL every partner is sent to, unless excluded. Skip internal loader and redirect immediately – whether PalDock’s loader waits for the pingtree or hands over straight away. Include results in redirect – whether the results travel in your page’s URL as query parameters. Partners with Override & Detailed Response – which partners may send their own URL and receive the detailed response immediately. Partners without Default External Final Page – which partners are excluded from the default URL. On the request: sync=1 – the API call waits for the pingtree instead of answering immediately. external_redirect_url – your own URL, instead of the default. Requires the override permission. external_redirect_url_results – full channel detail, or just status and type. True by default. Four of the six offer settings are outside the partner’s control, so a partner cannot fix a missing loader or missing query parameters on their own side. Two setups that work A. Let PalDock wait. Skip internal loader disabled, Include results in redirect enabled. The Internal Final Page holds the customer on its loader until the pingtree finishes, then redirects to your page with the result already in the query string. Your page is static and renders once from the URL. No polling and no JavaScript needed for the data. The customer looks at a PalDock loader for as long as the pingtree takes. B. Show your own loader. Skip internal loader enabled. The Internal Final Page redirects to your page straight away, while the pingtree is still running. Your page shows its own loader and polls until the result is ready. The customer is in your branding the whole time. You have to handle the waiting state as well as the finished one. Pick A when your page is rendered server-side. Pick B when the wait is long enough that the customer should spend it looking at your site. Getting the data From the query string. With Include results in redirect enabled, the results are appended to your URL as query parameters. About the lead: process_id, origin_id, status, is_finished, items_total, successful_items. The url field itself is not appended. About each channel, flattened with the item index in the name: item0_channel_id, item0_channel_name, item0_status and so on, then item1_ for the next channel. Empty values are dropped rather than sent as blanks, so do not rely on every key being present. By polling the Process API. GET https://api.paldock.com/api/{tenant}/processes/{process_id} Watch the status code, because two different objects come back from this endpoint: 202 is the External Final Page response, the same object the redirect flattens. Here url holds the resolved external page URL. 200 is the internal Final Page response, which has a different shape and is not what you want. Polling works in both setups, so even in setup A you can poll if Include results in redirect is off. Knowing when it is finished is_finished is the only reliable signal. false, the pingtree is still running. What you read is a snapshot and channels can still change. true, it has reached a terminal state and nothing more will change. Do not infer this from the statuses. A channel sitting in waiting may still be answered. If you send sync=1, the API call itself waits for the pingtree, so the response may already carry the finished result and there is nothing to poll for. url still points at the Internal Final Page even then. See API integration. How much detail you get external_redirect_url_results controls the shape of items. True by default. true, the full array: channel_id, channel_name, status, type, redirect_url, send_id and any exs_1 to exs_5. false, a basic array with only status and type. The value is taken from the request that created the lead and is remembered for that lead. Polling later returns the shape chosen at submission, so you cannot switch it on afterwards. Use false when your page only needs to know how it went, true whenever you render the channels themselves. Who gets what Two lists, and each does something different. Partners without Default External Final Page decides who gets an external page at all. A partner on this list is not sent to the default page and stays on the internal Final Page. Everyone else goes to the default page. Partners with Override & Detailed Response does two things: The partner may send external_redirect_url and be sent to their own page instead of the default. This is the only way to override the URL. A partner who is not on the list and sends the parameter has it ignored. The partner receives the detailed response immediately, in the API response that creates the lead. A partner who is not on the list gets the standard response instead, which carries no items. The list controls when the detailed data arrives, not whether it can be reached. Any partner with an external page can poll the Process API and get the same items, because the shape there depends only on external_redirect_url_results, which is true by default. Treat the list as a convenience for trusted partners, not as a way to keep channel data private. The three outcomes: On neither list. The partner goes to the Default External Final Page, gets the standard response on creation, and reads the results by polling. On the override list. The partner can send their own URL and gets the detailed response straight away. On the exclusion list. The partner has no external page and stays on the internal Final Page. Both lists fail quietly. A partner sending external_redirect_url without the override permission lands on the default page and nothing tells them why, so check the list first when a partner reports the wrong page. The two lists are independent, so a partner can be on both. Being on the override list does not exempt them from the exclusion list. The URL and its placeholders Both the default URL and external_redirect_url support placeholders that PalDock fills in: {process_id} – the process ID of this lead. {owner_id} – the affiliate the lead is attributed to. {data_<field_name>} – any submitted field value, for example {data_first_name}. Values are URL-encoded when they are inserted. A placeholder that matches nothing is replaced with an empty string rather than left in the URL, so a typo produces a silently missing value instead of an error. external_redirect_url must be fully URL-encoded, including &, ?, { and } inside the value, so the whole thing is read as one parameter rather than several. What comes back About the lead: process_id – identifies the lead. Use it for polling. url – the Internal Final Page when the lead is created, the resolved external page when polling. origin_id – the Origin ID of the click or lead this came from. See Conversion IDs explained. status – the overall state, using the same values as the channels below. is_finished – whether processing is complete. items_total – how many channels the lead reached. successful_items – how many accepted it. About each channel, in items: channel_id – the channel’s ID, shown in the pingtree editor. Match on this. channel_name – the channel’s visible name. status – ok, fail, processing or waiting. See Pingtree Distribution. type – the channel’s distribution type: exclusive, non_exclusive, auction or choice. redirect_url – where the advertiser wants the customer sent. Empty when the channel did not accept. send_id – the Send ID for this one channel. One lead going to five channels produces five Send IDs. Use it to match a later postback to the right channel. exs_1 to exs_5 – extra values from the advertiser’s response, where the integration maps them. Only present when the advertiser returned them. Channels set to Hidden never appear in items, so items_total can be higher than the number of entries you receive. origin_id and send_id are not the same thing. The Origin ID belongs to the lead and there is one of them. A Send ID belongs to one attempt at one channel, and there is one per item. Building the page Match on channel_id. It is stable and visible in the pingtree editor. Names change, IDs do not. The pattern that works on a comparison site is to prepare a hidden row for every channel in advance, each tagged with its channel ID, and reveal the rows that came back with ok. Your page then needs no logic beyond showing and hiding, and it already has the logos, names and copy, because it is the same data your comparison used before the form. Alongside the successful channels you can show offers outside the pingtree and display ads. The page is yours. When there is nothing to compare If the result has a single item and that channel is Exclusive or uses Priority redirect, there is nothing to compare. Send the customer straight to redirect_url. The redirect flow already does this and skips the external page in that case. Decide separately what to show when no channel accepted. That page will be seen, and an honest message is better than an empty comparison table. #### Feed structure A Feed Structure defines the format of product feeds imported into PalDock. Feeds contain product details (such as name, price, availability) and can be used by affiliates or in lead distribution logic. Used for importing data from external sources (CSV, XML, API). Fields can be mapped and extended with calculations or transformations. Powers product display for affiliates and supports logic in pingtrees and FinalPages. It describes rows, not a submission This is the one structure where nobody is filling anything in. A form structure describes one lead created by one person. A feed structure describes the shape of every row in an imported file, and the same structure is applied to all of them. That changes what the advanced options are for: Modify is the one you will use most. Prices arrive in the wrong currency, names arrive with the brand attached, availability arrives as 1 and 0. Modify normalises them on the way in. Validation decides what happens to a row that does not fit, rather than what a visitor is told to correct. AutoComplete has nothing to suggest to, so it does not apply here. Nothing is waiting for it A feed runs in the background on its own schedule, not while somebody watches a loading screen. The synchronous limit does not apply, so a feed scenario can take far longer than a form scenario and can call a slow service without costing you a conversion. See Limits and timeouts. 👉 For details about field types, validation, Modify, and translations, see the other pages in this section. #### Field format Most APIs do not want a flat list of values. They want objects inside objects, or lists of them. In PalDock you do not build that structure anywhere, you write it into the field name and PalDock assembles the payload from it. Objects A dot means “inside”. Everything before the dot is the object, everything after it is the field within it. customer.name customer.email sends json { "customer": { "name": "John Doe", "email": "john.doe@example.com" } } Nest as deep as the API needs, one dot per level: customer.address.city. Lists A number means a position in a list. Counting starts at zero, so the first item is 0. orders.0.product orders.0.price orders.1.product orders.1.price sends json { "orders": [ { "product": "Laptop", "price": "1200 EUR" }, { "product": "Phone", "price": "650 EUR" } ] } The same works for a list inside a list. data.0.0 and data.0.1 are the first and second value of the first list: json { "data": [ ["first", "second"] ] } Mixing them Objects and lists combine freely, because both are just steps along the same path. customer.name customer.email orders.0.product orders.1.price If it helps, think of an object as a folder and a list as a numbered set of files inside it. The field name is the path that gets you to the exact spot. Order does not matter You do not have to keep related fields together in the editor. PalDock groups them by name when it builds the request, so these four produce exactly the same payload whichever order they appear in: customer.name orders.1.price customer.email orders.0.product Sort them however makes the editor easiest to read. Getting it right Check the API documentation for the structure they expect and copy it path by path. If you have an example payload from them, jsonpath.com with JSONPath Plus is a quick way to confirm which path leads to which value. The same notation works in the other direction. When you read a response, {parsedBody.offers.0.offerId} walks the same path through what came back. #### Field settings Field settings control how a field behaves in forms, APIs, and integrations. They define its technical identifier, display label, default behavior, and rules for visibility. General Properties System name – the internal identifier of the field. Used in integrations mapping. Type – the field type (Text, Number, Checkbox, etc.). Determines what kind of data can be collected. See Field types for more information. Label – the name shown to end users in forms. Placeholder – helper text displayed inside the input when it is empty (e.g. “Enter your ZIP code”). Default value – a pre-filled value that appears unless the user overwrites it. Input mode – defines the expected input method in the frontend (e.g. text, tel, email). It mainly affects mobile devices, where it prompts the appropriate on-screen keyboard. See the section Input mode below for more information. Value format option – an optional mask that formats the value in the frontend (e.g. ### ### ### for phone). This setting overrides the default mask defined by the field type. Example value – a sample of what a correct value looks like. Note – a description of the purpose or usage of the field. Example value and Note are not internal Both appear in the API documentation your affiliate partners see for this offer. A partner reading that documentation sees the system name, the type, whether the field is required, the example value and the note. Write them for that reader. An example value of 1234567 on a company ID field, and a note explaining which register the number comes from, saves a support ticket. An empty example value means the partner guesses. Conditional Display Not Show If System Name Equals – hides this field if another field’s system name has the specified value. Show Only If System Name Equals – displays this field only if another field’s system name matches the specified value. Both settings compare against one exact value. There is no “contains”, no “is not empty” and no way to combine two conditions on the same field. Checkboxes Options that define the behavior of the field: Required field – the field must be filled before submission. Editable – the field can be modified by the user. Hidden field – the field is stored but not shown in the form. ⚠️ Required is enforced in the form. A lead arriving through the API is checked for its format only when the field is required, so a field left optional accepts whatever the caller sends. If a value has to be correct whatever the source, add a regex or a validation scenario. See Field validation. Field-Type Specific Options Some field types add extra configuration sections: Checkbox Accordion – includes a Description section to enter the explanatory text shown with the field. Select / Radio Button – include a Values section to define the available options for selection. Slider – includes Min and Max to set the range the user can choose from, and Step to set how much one move changes the value. Each entry in the Values section has two parts. The value is what gets stored on the lead and sent to an integration. The label is what the user reads on the form. When a lead is created over the API, the caller sends the value, not the label. Input mode The Input mode setting defines the expected input method in the frontend. While it has little impact on desktop browsers, it is important on mobile devices, because it determines which type of keyboard will appear. Supported input modes: text – default mode, shows the standard keyboard for free text. tel – optimized for telephone numbers, shows a numeric keypad with 0–9, +, *, #. We usually recommend using this input mode even for phone numbers, as it provides a better keyboard layout. email – optimized for email addresses, shows @ and . keys prominently. url – optimized for URLs, shows /, ., and www. shortcuts. numeric – numeric keypad for entering numbers only (does not allow symbols like + or -). decimal – numeric keypad with a decimal separator (“,” or “.” depending on locale). 👉 Tip: Always choose the input mode that best matches the expected content. This makes form filling faster and reduces input errors, especially on mobile. Special use cases Hidden field with default value – You can hide a field from the user and set a default value in the field settings. This ensures that every record created with this structure contains the same constant value, even though the user never sees the field. Typical examples include internal flags, campaign IDs, or fixed country codes. Hidden field filled by a scenario – Instead of a static default, you can hide a field and let its value be filled automatically. Using Modify, the system can bring in values from an external service through Connection Creator. For example, you might provide a company ID in one visible field, and have the system automatically fill hidden fields such as company address, postal code, or operator. #### Field types Field types define what kind of data can be collected and processed in a specific field. Each field type has its own characteristics and use cases: Text A free-form field that accepts letters, numbers, and special characters. It is most commonly used for names, addresses, or general inputs where no strict data type is required. Number A numeric field that only accepts digits. It is used for quantities, amounts, ages, or any value that must be stored as a number. Text or special characters cannot be entered here, and if the number begins with a leading zero, that zero will be automatically removed. You can set a Min and a Max in the field settings. Both are applied in the form. Do not use Number for a value that only looks numeric, such as a postal code, a bank account or a national ID. Those need Text, because the leading zero matters. Checkbox A binary field with two possible states: selected or not selected. It is typically used for consents, confirmations, or simple yes/no choices. For this field type, validation does not apply, so it is hidden in the field settings. The value of this field must be either true or false (when used in API) Checkbox Accordion An extended version of the checkbox that allows additional descriptive text or expandable content. This is useful when a single choice requires explanation, such as terms of service or grouped agreements. For this field type, validation does not apply, so it is hidden in the field settings. When this field type is used, an additional Description section appears in the field settings. Here you can provide the content for this field. The value of this field must be either true or false (when used in API) Date A field for selecting calendar dates. It ensures that the input follows a valid date format and is commonly used for birthdays, contract dates, or scheduling information. Select (Dropdown) A field that lets the user pick one value from a predefined list of options. It is suitable when the available answers are limited and should be standardized. For this field type, validation does not apply, so it is hidden in the field settings. When this field type is used, an additional Values section appears in the field settings. Here you can provide the list of values for this field Multi-Select (Dropdown) A field that lets the user pick multiple values from a predefined list of options. Each selected value is displayed as a removable tag inside the field. It is suitable when users may need to choose more than one option from a standardized set. For this field type, validation does not apply, so it is hidden in the field settings. When this field type is used, an additional Values section appears in the field settings. Here you can provide the list of values for this field. Radio Button A field where the user selects exactly one option from a predefined set. Unlike dropdowns, all choices are displayed on the form, making selection more visible and mobile-friendly. For this field type, validation does not apply, so it is hidden in the field settings. When this field type is used, an additional Values section appears in the field settings. Here you can provide the list of values for this field Country A field where the user picks a country from the list maintained by PalDock. Use it instead of a Select with your own country list, so the same country is written the same way in every structure and every integration. For this field type, validation does not apply, so it is hidden in the field settings. The list of values is provided by PalDock, so no Values section appears in the field settings. Phone A specialized field for entering phone numbers, including an international prefix. It ensures that the input is structured as a valid phone number rather than free text. The prefix and the rest of the number are held separately. With global fields the prefix lands in g_phone_prefix, the number in g_phone, and the two joined together in g_phone_full. Email A field intended for email addresses. It accepts inputs in email format only and is used for communication, user accounts, or identification. Tag Input An interactive input where each entered value becomes a tag (chip). Users type a value, press Enter/Tab/Blur, and it’s converted into a separate tag. Stored value: string[] – each tag is one array item. Best for: values that may contain spaces, commas, or special characters. List Input A textarea-based input where each line represents one value. Users can paste or type lists directly, e.g. copy from a spreadsheet. Stored value: string[] – each line is one array item. Best for: bulk operations and mass imports. Delimited Input A single text field where multiple values are entered in one line and separated by a delimiter (comma, semicolon, pipe, etc.). Stored value: string[] – the text is split into an array on submit, based on the chosen delimiter. Best for: simple cases or when delimiter-based formats are explicitly required. Slider A field where the user picks a number by dragging a handle along a track instead of typing it. Use it when the value is a rough amount rather than an exact one, such as a requested loan amount or a term in months, and when seeing the available range helps the user decide. For this field type, validation does not apply, so it is hidden in the field settings. When this field type is used, additional Min, Max and Step settings appear in the field settings. Min and Max set the range, Step sets how much one move changes the value. The stored value is a number, so the user cannot submit anything outside the range you defined. #### Field validation Validation ensures that data collected in forms and structures is correct, usable, and consistent. It helps prevent invalid inputs from being stored in the system and allows you to enforce business rules on top of basic field constraints. Apart from the basic validation enforced by field type, you can use additional validation methods ranging from simple rules to advanced external services. What validation applies to Two rules cover every case: Required decides whether the field may be left empty. Everything else runs only on a field that has a value. An empty optional field is not checked at all, so a regex or a validation scenario never turns an optional field into a required one. This is the same whether the lead comes from a form, an embeddable form, or the API. A partner sending leads over the API is held to the same rules as a visitor filling in the form. Basic validation Some field types enforce a minimal level of validation: Number – only digits are allowed, leading zeros are removed. Phone – must be entered as a valid number with prefix. Email – must contain a valid email pattern. Date – must follow a valid date format. Checkbox – must be true or false. Select and Radio Button – must be one of the values defined on the field. These checks belong to the field type, so there is nothing to configure. See Field types. Regex validation You can configure regex validation rules to enforce custom patterns (e.g. a national identifier, a licence plate). You can describe the intended rule to AI to generate the regex, and then test it on multiple values using a tool such as regex101.com. A regex is the right tool when the rule is about the shape of the value and nothing else. If the rule needs to look the value up somewhere, use a validation scenario instead. External validation through Connection Creator You can use the Connection Creator to call an external service for validation. Typical examples include: Checking whether a phone number or email actually exists. Verifying a company ID against an official database. Bank account to validate bank account numbers against banking standards. Personal ID check to validate identifiers against checksum algorithms or national registries. Domain check to validate that a domain exists, has active DNS records, or belongs to a specific organization. Many other validation scenarios can be implemented this way. How a validation scenario works The scenario is built in the Connection Creator, where it calls the service and decides what the answer means. What it hands back to the field is one of two results: the value is accepted, or the value is rejected and the visitor is asked to correct it. Build a branch for every answer the service can give, including the one where it does not answer at all. Handle the outage This is the branch people leave out, and it is the one that costs money. If the service is down and nothing in the scenario handles that, the field is never accepted and nobody can submit the form. An outage at the provider becomes an outage at your offer. Send that case to an accepted result instead. The value was not verified, but the lead is still collected. You lose one check for as long as the provider is down. Without it you lose every lead in that time. Decide this per field. A check that exists to keep data tidy should always fall back to accepted. A check that decides whether you may take the lead at all is the rare case where blocking is right, and even then you want to know how long you would be blocked for. Validation can also record what it found A scenario can write a value into a field on its way through, so a check can both verify something and store the answer. An insolvency check can accept the lead either way and put yes or no into a field the advertiser receives. When you only want to store a value and never block anything, use Modify instead. More than one scenario on a field A field can have more than one validation scenario. All of them must succeed for the value to be accepted. One failure rejects the field, whatever the others returned. The order things run in Basic validation and regex run first, on every field that has a value. Validation scenarios run only if that first pass found nothing wrong, anywhere in the form. So a value that fails its regex never reaches the external service. That saves a call, but it also means a scenario you are testing will not run at all while another field is still invalid. What to watch out for ⚠️ Validation through an external service can break the entire system if it is set up incorrectly, preventing the form from being submitted and the lead from being created. Validation is always a trade-off between data quality and conversion rate. Stricter validation improves data accuracy, but it can also frustrate users filling out the form and cause them to abandon it before submission. Regex validation. If a mask or regex validation fails, the user will be prompted to correct the input before submission. Always ensure that the validation rules are accurate so the form remains submittable. Prefer simpler expressions over overly complex ones, as complicated patterns can lead to unexpected behavior. Unhandled responses. Write a branch for every answer the service can give, including the ones you do not expect. A response that matches no branch leaves the scenario with nowhere to go. Timeouts. If an external service takes too long to respond, users are stuck waiting with a loading spinner until the request finishes. This creates a poor user experience and increases the risk of abandonment. Set the timeout on the HTTP node, and remember that the whole scenario runs while the visitor waits, so it has to finish inside the synchronous limit. See Limits and timeouts. 👉 Always balance validation strictness with usability. For mission-critical checks, use external validation, but configure fallbacks and reasonable timeouts to prevent the system from breaking. #### Filters Filters narrow down the data shown in tables, reports, and logs. PalDock has two of them. Large filter: a full filter with a field, an operator, and a value. Use it for anything beyond a single column. Small filter: a quick filter applied straight to one column, shown inline in the table. Large filter Click the filter button and a submenu opens with the first empty row ready to fill in. Each row has three parts: Field: what you are filtering. Fields are grouped into categories, because the list is long. Operator: contains, equals, and so on. Which operators are offered depends on the field type. Value: one value or several, again depending on the field type. Every row you add narrows the result further. Rows can be removed one by one, or cleared all at once. Small filter The small filter belongs to a single column and sits in the table itself. It is meant for quick lookups rather than analysis. Some tables offer only this one. In Offers, List for example, filtering is done through the small filter on selected columns. You do not have to show a column to filter by it Tables can be filtered by: Displayed columns Hidden columns Metrics that are not available as columns at all This matters most in reports, where you often want to restrict the data without adding another column to an already wide table. Filtering by country, tag, or transaction type works the same whether that column is on screen or not. What you can filter by Beyond the columns of the report itself, the same set of filters is available across reports, logs, and the transactions report: Advertiser, offer, affiliate Transaction type: prospect, sale, or a custom type Origin type: click or lead Source type: link, iframe, or API Category Tags: on affiliates, offers, and advertisers Offer country and affiliate country affs1 to affs10 and adv1 to adv10, the custom values passed with the click or the lead The custom values are most useful in the logs and in the Transactions report, where you are looking at individual rows. In aggregated reports they can produce a very long list of values, since anything the partner sends ends up there. Filters built into each report Every report also carries the filters that make sense for what it groups by: Performance report: advertiser Affiliate report: offer Advertiser report: affiliate, offer Offer report: affiliate, advertiser Pingtree report: no additional filter What partners can filter Affiliates and advertisers use the same reports as you, with two limits. They see only their own data. A filter never widens that. Affiliates cannot filter by channel. Which channel bought a lead is not something a partner is shown, so that filter is not available to them. Not the same as offer filters Report filters only change what you see. The filters on an offer decide whether a lead is processed at all. The two look similar and do entirely different things. #### First steps to get started This page takes you from an empty workspace to one that records clicks, leads, and conversions. Read it once before you start clicking, because two of the decisions here are easier to make now than to change later. Decide two things first Workspace currency One currency for the whole workspace. Reports convert every amount into it and show one total, while transactions, balances, and invoices stay in the currency of the offer they belong to. See Currency. Users cannot pick their own. Everybody in the workspace sees the workspace currency. It can be changed later, but the change recalculates historical report values, so it is not something to do casually. Pick the currency you invoice in. Workspace language The workspace has a default language, and each registered user can switch to their own. Nothing depends on it beyond what people read. Use the defaults A new workspace comes with prepared defaults, including a default advertiser and a default commission group. They exist so you can build the whole chain now and fill in the detail later. Everything below can be created without completing every field. Offers, commissions, and accounts all accept the minimum and let you come back. Step 1: create an offer Most settings are already sensible. What you actually need to decide: Commission amounts Two numbers, what your partner gets and what the advertiser pays you. A network earns the difference between the two. An advertiser is setting a maximum CPA, which the profit per partner is measured against. An affiliate with their own workspace can set both the same. It is for you and any sub-affiliates later. ROI and the other derived metrics come from the difference between them. See Commission amount. A commission is a rule saying when a transaction is created from a conversion. Some conversions PalDock creates itself, such as clicks and leads. Others arrive through tracking, such as prospects and sales. See Conversion, Commission, Transaction. Commission group and advertiser Stay with the default commission group for now. Custom groups are how you pay different partners differently, and affiliates can be assigned to them later. Assign the correct advertiser before you go live. The default advertiser gets you moving, but conversion tracking depends on the real one being there. Promotion method Choose affiliate link, iframe, or API. See Allowed Delivery method. Affiliate link: paste the advertiser’s URL and add the tracking parameter pcid. It carries the Origin ID of the click, which is what the advertiser sends back with the conversion. See Affiliate link. iframe: configure the form structure and pick a design. The defaults work to start with. API: configure the form structure as well. The API does not deliver anything until the offer has distribution channels paired with an integration, which you can add later. See API integration. Save the offer. Step 2: set up tracking The minimum is a postback from the advertiser, with a pixel as backup. Relying on one method means a misconfiguration on their side costs you conversions. Postback: in Tracking, Incoming Postback. Generate the documentation and send it to the advertiser so they call the right URL with the right parameters. See Tracking S2S Postback. Conversion pixel: in Settings, Tracking, Conversion types and pixels. Pick the conversion type, prospect, sale, or your own, and the create action. See How to set up pixel tracking. Update pixel: same place, update action. This is what adds cookie and URL data, such as Google or Meta identifiers, to a lead that already exists. See Update pixel. Whatever method the advertiser uses, they have to send an identifier. The Origin ID, the value your link carried as pcid, or their own external ID together with the advertiser ID. Without one of those, a conversion cannot be matched to anything. See Conversion IDs explained. They can also send more, such as a value for percentage payouts, or a transaction type to separate prospects from sales. See Tracking parameters. If affiliate links are all you need, you are done here. Step 3: build the integration Only for iframe and API, where PalDock has to deliver the lead somewhere. It is a good moment for it, since you are waiting on the advertiser anyway. First, update the default form structure or create one matching the data you want to collect and pass on, then adjust the form design. Then create the integration in the Integrations section. It works like Zapier or Make: add nodes, connect them, apply conditions and modifications, and build against the advertiser’s API documentation. See How to integrate anything. Four things the integration has to define: Which request prechecks the lead, and what response means it may continue. Optional. Which request sends the lead, and what response means it was accepted. Required. Where the advertiser’s external ID is in the response. Store it. Without it a later postback has nothing to match against, and you need it whenever they cannot return the Origin ID. Where the redirect URL is, if the customer should be sent on. Optional. Then test it Do not wait for real traffic to find out whether it works. See Test the Offers, and when something does not appear, the logs tell you where it stopped. #### first-regex-match The first-regex-match operation pulls a piece out of a value using a pattern. It finds the first thing that matches and returns just that. Use it when the value you need is buried in text: an order number in a sentence, a code inside an identifier, digits inside something formatted. How it works You write a regular expression in the parameter. The operation searches the value and returns the first match. Pattern: \d+ Value: Order n. 12345 Result: 12345 Pattern: [a-z]+ Value: 123 ABC xyz Result: xyz Pattern: ^\d{2} Value: 5501150325 Result: 55 The whole match is returned, not a captured group. Brackets in your pattern help you describe what to look for, but the result is always the entire matched section. When nothing matches The result is an empty string. Not the original value, and not an error. The field ends up blank. That is the behaviour to plan around, because an empty field usually travels on quietly. The advertiser receives nothing where they expected an order number, and the rejection that follows will not mention the pattern. The same thing happens when the pattern itself is invalid. A stray bracket or an unescaped character gives you an empty result rather than a complaint, so a broken pattern looks exactly like a value that did not match. Check for the empty case afterwards. A condition on the connection leaving the node, or a following step with the condition is empty, is enough to tell the two situations apart from a lead that simply had nothing to find. Only the first one If the value contains several matches, you get the first. There is no way to ask for the second, or for all of them. When you need more than one piece out of the same value, extract each into its own field, each with its own pattern anchored to a different position. Test the pattern first Write the pattern somewhere you can see it working before you paste it into PalDock. regex101.com shows you what matches and why, which the editor cannot. This matters more than usual here, because of the silent failure. A pattern that is subtly wrong produces the same empty string as no pattern at all. If you generate the pattern with an AI tool, test it anyway. They are good at plausible patterns and less good at correct ones, and the failure mode here gives you nothing to notice. Changing rather than extracting first-regex-match takes a piece out and throws the rest away. To keep the value and rewrite part of it, use regex-replace, which is where capturing groups do what you would expect. Reference Patterns follow PHP’s PCRE syntax. See PHP: Pattern Syntax. #### Form structure A Form Structure defines which fields are collected when a lead is created. It acts as the blueprint for forms, API payloads, and partner integrations. Ensures all leads follow a consistent format. Defines which fields are required and optional. Used in all forms generated by PalDock and in incoming API traffic. Typical use cases: when each offer or product has its own specific field requirements. One structure, three ways in A lead can reach PalDock through a hosted form, an embeddable form on the affiliate’s site, or the API. All three are served by the same structure. A field you add appears in all of them at once, including in the API documentation your partners read. So does a field you make required, which is worth remembering when partners are already sending leads. How it connects to offers and integrations A structure is attached to an offer, and an offer can have more than one. Two landing pages that differ by a single field can share one offer instead of being duplicated. See Multiple Structures for Offers and Integrations. An integration is built on exactly one structure. Its fields are what you map into the advertiser’s request, so an integration can only send what its structure collects. If an advertiser needs a value that is not in the structure, add the field there first. Collecting it, hiding it, or filling it with Modify are then all options. Deciding how many you need One structure per offer is the normal case. Add another when the fields genuinely differ, not when only the wording differs. The same fields, different labels is a job for Translations or for editing the label, not a second structure. The same fields, different rules or scenarios does need a second structure, because validation and Modify are set per field. Different fields obviously needs a second structure. Every extra structure is another place to maintain when an advertiser changes what they want, so the cost is real but it is paid later. 👉 For details about field types, validation, Modify, and translations, see the other pages in this section. #### format-date The format-date operation writes a date a different way. The date itself does not change, only how it is written. Use it when the advertiser wants a format your data does not use. How it works You give it a format pattern and it rewrites the value to match. Value: 2024-02-21 Pattern: d.m.Y Result: 21.02.2024 Value: 2024-02-21 15:30:00 Pattern: Y-m-d H:i Result: 2024-02-21 15:30 Value: 2024-02-21 15:30:00 Pattern: Y-m-d Result: 2024-02-21 That last one is how you drop the time from a date that carries it. Patterns worth knowing Y-m-d gives 2024-02-21, the international format d.m.Y gives 21.02.2024, common across Europe m/d/Y gives 02/21/2024, the American one Y-m-d H:i:s gives 2024-02-21 15:30:00, a full timestamp l, j F Y gives Wednesday, 21 February 2024, written out The letters are case sensitive. Y is a four-digit year and y is two, m is a zero-padded month and n is not. An unreadable date stops the flow If the value cannot be read as a date, the node fails with an error and the branch stops there. This is different from unix, which quietly hands back the original value. Here you find out, which is better, but it means an empty or malformed date field takes the run down with it. So put a condition on the step. Running it only when the field is not empty avoids the most common cause by itself. Starting from a timestamp A Unix timestamp is a number, not a date, and reading it as one gives nothing useful. Put an @ in front of it first, so 1735084800 becomes @1735084800, which is understood as a timestamp. Use prefix for that, then format-date. The @ belongs in front of the value, not in front of the pattern. Time zones format-date rewrites the text and nothing else. It does not shift the date into another time zone, so a date recorded in UTC stays UTC no matter how you write it. If the advertiser needs a different zone, that is a separate problem and format-date will not solve it. Working with the other date operations modify-date shifts a date forwards or backwards unix turns it into a timestamp format-date writes it a different way Shift first, format last. A step that adds thirty days followed by a step that formats the result is the usual way to send an expiry date. Reference Patterns follow PHP’s date formatting. See PHP: DateTime::format for the full list of letters. #### from-base64 The from-base64 operation decodes a Base64 value back into what it was. It is the reverse of to-base64. How it works Value: aGVsbG8= Result: hello Value: MTIzNDU= Result: 12345 Value: eyJpZCI6MX0= Result: {"id":1} Invalid input does not fail This is the one to watch. Decoding something that is not Base64 does not produce an error and does not leave the value alone. Characters the decoder does not recognise are skipped and the rest is decoded anyway, so you get a shorter, meaningless string. Nothing about that result announces itself as wrong. It is not empty, so a check for an empty value will not catch it, and it travels on to the advertiser looking like an ordinary value. So only decode where you know the value is encoded. If a response sometimes carries Base64 and sometimes plain text, put a condition on the step rather than decoding everything and hoping. When you need it Reading a response that arrives encoded. Some APIs return a payload as Base64 and you want the contents. Checking what is inside a token. The parts of a JWT are Base64, so decoding one shows you what it claims. Recovering something you encoded earlier, when a later step in the same flow needs the original. Binary data Base64 can hold anything, including data that is not text. Decoding a file or an image into a field gives you bytes that make no sense as characters and will usually break whatever you send them to. Decode into a text field only when you know the original was text. Reference See PHP: base64_decode. #### Group changes Bulk Edits allow you to make changes to multiple rows in a table at once, instead of editing them one by one. This feature saves time and ensures consistency when managing larger datasets. How It Works Hidden by default – checkboxes for row selection only appear when you hover over the header or the first column of a row. Select rows – choose one or more rows manually Click Edit – once rows are selected, the Edit button becomes active. Set up bulk changes – define what you want to do using the available options (see below). Apply changes – you can update, delete, or otherwise modify selected rows. Available Options When performing a bulk edit, the following options are available: Rows – the rows you selected manually, or those imported by pasting a list of IDs/values (for example from a previously exported and modified Excel file). Action – what should happen (e.g. Edit, Delete). Field – which field/column should be updated (includes both visible and hidden editable fields). Value – the new value to insert. ⚠️ Important: Bulk edits will overwrite existing values in the selected rows with the new ones you provide. Any current values that are not specified in the update will be permanently lost. Typical Use Cases Transaction Report – Change statuses or approve multiple transactions at once Offer Management – Update tags, categories, access levels, or location for multiple offers General Management – Apply bulk changes to affiliates, advertisers, commissions, or other entities Basically, anywhere in PalDock where you can edit items individually in a table, you will also be able to apply bulk edits. #### Highlights Highlights are the row of key numbers above the table, and they are what the chart plots. They appear on the Dashboard, in reports, and in the logs. Each Highlight is one metric, summed over whatever you are currently looking at. They follow the date range, the filters, the result type filter, and the reporting time basis, so the number above the table always matches the table itself. Default metrics A new workspace starts with six: Clicks Leads Transactions Costs Revenues Profit Any performance metric can be used as a Highlight, including the per lead, per click, and per transaction metrics such as EPL, CPC, and ACV. See Advanced columns for what each one means. How Highlights behave The behaviour differs depending on what the report is built around. Reports over time In reports that show data by date, such as the Performance report, each Highlight is the sum of that metric for the selected period. Every Highlight has its own colour, and each active one is a line in the chart. Clicking an active Highlight switches it off. Clicking an inactive one switches it on. Several Highlights can be active at once. Reports by entity In reports built around entities, such as offers or affiliates, the chart shows one Highlight at a time, plotted across the top 10 rows. Showing every Highlight for every row would mean dozens of lines. The colour belongs to the row, not to the Highlight. Clicking an inactive Highlight activates it and deactivates the previous one. The table is sorted by the active Highlight, highest first. To see several Highlights for a single row, first clear the row selection with the checkbox icon. See Show rows in chart. Editing Highlights Highlights are edited from the Dashboard, and the set you choose applies everywhere they appear. Add a Highlight: click Edit Overview to enter edit mode. The button then reads Add, since you are already editing. Remove a Highlight: hover over it, click the trash icon, and confirm. In edit mode the Highlights are marked in the same edit style used elsewhere in PalDock. There is no way to change what an existing Highlight shows. To swap one metric for another, remove the one you do not want and add the one you do. #### How the commission is selected When a conversion is recorded, PalDock looks for commissions that apply to it. This page explains which ones are found, how many of them run, and why a matching commission still might not create a transaction. Step 1: matching the conditions A commission matches when every one of its conditions either matches the conversion or is left empty. Empty means “any”. Offer Advertiser on workspace commissions, or the affiliate on partner commissions Conversion type Source, read from the original click or lead, not from the conversion that arrived last Channel, when the offer uses Pingtree Commission group of the affiliate who owns the conversion Step 2: how many commissions run PalDock collects every commission that matches. What happens next depends on where the conversion came from. Clicks and leads created by PalDock from an affiliate link, iFrame, or API: all matching commissions run. One lead can create several transactions at once, one per commission. Everything else, meaning pixel, postback, Tracking API, and manual import: only one commission runs, even if several match. If the tracking request contains a Commission ID, that commission is used. It still has to match the conditions above, so a Commission ID that belongs to a different offer or conversion type will not be applied and no transaction is created. See Multiple Commissions for the Same Conversion Type. Step 3: which one runs when only one can When only one commission can run and several match, a filled condition beats an empty one. PalDock compares them in this order: Offer Channel Conversion type Source Commission group A commission limited to one offer therefore beats a commission that applies to all offers. If two commissions are still equal, commission order decides and the first one in the list wins. The commission is chosen before its status is checked. If the winning commission turns out to be inactive, no transaction is created and the next commission in the list is not used instead. Step 4: the partner commission Once the workspace commission is chosen, PalDock picks the partner commission below it. The affiliate gets the commission set for their commission group. If that group has no commission set, the one without a group is used. This happens for every workspace commission that runs, so the workspace transaction and the matching partner transaction are always created together. Step 5: the final checks A commission that was chosen still creates nothing if any of the following is true. The commission is inactive. The conversion falls outside the commission’s active period. The dates are compared against the time the conversion happened, not the time the tracking arrived. A postback that comes in late still uses the commission that was valid when the conversion was created. The recurrence limit for that commission has already been reached. The conversion is not valid, for example because it was rejected or marked as a duplicate. The conversion was created by a commission itself. Conversions that PalDock creates to hold a transaction of a different transaction type never trigger commissions again. Why no transaction was created Check these in order in the conversion log. No commission matches the conversion type. A Commission ID was sent that does not match the rest of the conditions. The commission that won is inactive or outside its active period. The recurrence limit was reached. The conversion was deduplicated on the advertiser’s external ID. #### How to integrate anything This page is the practical route from an advertiser’s API documentation to a working integration. The Editor explains the tool. This explains the method. Before you start Have these ready: The endpoint and the HTTP method. How the request authenticates: a token, a header, a signature. Which fields are required, and in what format. Check whether the advertiser restricts access by IP address. If so, provide them with the PalDock outgoing IP address below. However, we highly discourage relying on IP whitelisting, as it is an outdated approach that tends to cause more problems than benefits. 159.69.100.31 159.69.101.229 What a successful response looks like, and what a rejection looks like. Test credentials, so you can send real requests without creating real leads. If any of these are missing, get them first. Most integrations that take a long time to build are missing one of them. 1. Create the integration Integrations live in the Integrations section. Click Add and either start from scratch or pick a ready-made one from the Library of Integrations. If the advertiser is already in the library and you use global fields, you may be finished in one click. 2. Add the Start node Every scenario begins with a Start node. Choose the type that matches what the scenario is for: Integration, Structure or Tracking. See Where Connection Creator is used. 3. Put the data into the right shape Advertisers rarely accept your data as it is. Phone numbers need a prefix stripped, dates need a different format, a country needs to become a code. Use a Modify node for this, not the HTTP node. Keeping the transformation separate makes it obvious later where a wrong value came from. 4. Send the request Add an HTTP node and fill in the method, the URL, the headers and the body. Values from the lead go in curly braces, for example {email}. Two settings on this node matter: Timeout, how long to wait for the answer. If a visitor is waiting on a loading screen, keep it low. Signature, if the advertiser requires the request to be signed. For nested payloads, see Field format. 5. Read the response An answer of 200 OK does not mean the lead was accepted. Most advertisers return a rejection inside the body with a perfectly normal status code, so read the body, not just the code. Store what you need with a Set node. The values worth storing almost every time: The advertiser’s own ID for the lead, into {external_id}. Without it you cannot match a later postback to this lead. The redirect URL, into {redirect_url}, if the visitor is sent onwards. The price, if the advertiser returns one. 6. Decide what counts as success Put a condition on the connection leaving the HTTP node, so only an accepted lead continues down the success path. Everything else goes down the other path. Be specific about what success means. Matching on a status code alone is the most common reason an integration reports accepted leads that the advertiser never received. 7. Finish the flow End the flow so PalDock knows the outcome. A rejection is a valid outcome, not an error, and it belongs in the reporting the same as an acceptance. See Reject reason and Refuse leads. PING and POST in a pingtree When an integration is used in a pingtree, it can have more than one Start node, because each flow has its own separate path. The PING flow has its own Start and its own End. The POST flow has its own Start and its own End. Never connect PING and POST directly. The two flows must stay separate, with no connection between them. Waiting, repeating and verifying Some advertisers do not answer immediately. Add a Wait node to pause before you ask again. Remember that the visitor stays on the loading screen while this happens, so watch the synchronous limit. There is no node that retries on its own. You build the loop: an HTTP node asks for the status, and a connection leads back to the Wait for as long as the answer is not final. Always put a Breaker in that loop. It caps how many times the flow may go round, so a lead the advertiser never decides on ends cleanly instead of failing on a system limit. If the lead has to be verified, that is usually a second HTTP request after the first one succeeds. If the advertiser calls you back instead of answering, use a Webhook node, which can wait far longer because nothing is blocked while it does. Saving values from responses You can store a value returned by a request and use it later in the flow, or after it. Predefined variables are listed in Tracking parameters. For your own variable, save it to a parameter with the prefix custom_ and reference it as {custom_anything}. Stored values are kept in the database, so they remain available to tracking and postbacks long after the run has finished. Test it before you go live Send a test lead and open the run in the log. Go node by node and check what each one received and returned. Test a rejection too, not only an acceptance, because that is the path that usually breaks silently. Common mistakes Treating 200 OK as acceptance. Not storing {external_id}, so postbacks cannot be matched later. Not storing {redirect_url}, so customers cannot be redirected to advertiser. Connecting PING and POST. A timeout so long that the visitor gives up before the flow finishes. #### How to set up pixel tracking This page covers placing the pixel, choosing when it fires, and fixing it when it does not. Where each pixel goes Initiation pixel: on every page of the site. Conversion pixel: only on the page that marks the conversion, whether pending or approved. It creates the conversion the moment it fires. Update pixel: fires only when the data layer contains an Origin ID. We still recommend placing it on the conversion page as well. If you implement the pixel directly in the page, put it as high in the <head> as possible. Google Tag Manager GTM is the most common integration, though not the best one. Place both scripts as Custom HTML tags. Which trigger to use GTM offers five triggers. The earlier the pixel fires, the more traffic it captures. Use the Initialization trigger. Consent Initialization: fires first, and is meant for consent management tags only. Do not use it for the pixel. Initialization: fires before everything except Consent Initialization. This is the one you want. Page View: fires as the browser starts loading the page. DOM Ready: fires once the page structure is built. Window Loaded: fires once images and scripts have finished loading. Latest and least reliable. Why GTM is not ideal Some ad blockers block the entire GTM container, and the pixel goes with it. Server-side GTM survives most of them, standard GTM does not. Adblock: does not block either setup. Adblock Plus, uBlock Origin, Ghostery: block standard GTM and server-side GTM alike. Safari ITP: affects standard GTM, not server-side GTM. Corporate VPNs: usually affect standard GTM. Behaviour varies by network. The safer options, in order: put the pixel directly in the page code, use server-side GTM, or accept standard GTM and back it up with a postback. When the pixel is blocked Set up an S2S postback alongside the pixel. It runs server to server, so ad blockers and missing cookie consent do not affect it. Fire it when the conversion is created, so both methods report the same event and PalDock keeps one conversion. Or fire it only on updates, when the advertiser approves or rejects. Deduplication on the external ID is what keeps the two methods from doubling your numbers, so make sure the advertiser sends it in both. Where the click ID is stored The cookie parameter of the initiation pixel decides this. cookie=1: a cookie. Recommended. cookie=2: localStorage. cookie=0: sessionStorage. ⚠️ localStorage and sessionStorage are not shared across domains or subdomains. They only work within the exact same origin, meaning the same protocol, domain, and port. If your homepage runs on the main domain and checkout on a subdomain, only a cookie carries the click ID across. If you cannot fire the pixel before cookie consent, you have to move the value yourself, for example through a URL parameter or your own backend. Troubleshooting The pixel never appears in the network tab Your site may have a Content-Security-Policy header that blocks our domain. The pixel then fails silently: nothing in the browser’s Network tab, while GTM still reports the tag as fired. To confirm, open DevTools, Console, and look for a message about a refused script and a Content Security Policy directive. To fix it, ask your developers to add our domains to the CSP: connect-src 'self' https://*.paldock.com https://paldock.com https://*.palpxl.com https://palpxl.com; Then check in DevTools, Network, that the requests go through. The pixel fires but nothing arrives Check the tracking log. If the request is not there, it never reached PalDock, so the cause is in the browser: CSP, an ad blocker, or a missing consent. If it is there but did nothing, read the outcome in Tracking errors and reasons. Conversions appear without an affiliate The initiation pixel is not firing, or is firing after the click ID is gone from the URL. Check that it is on every page and on the Initialization trigger. #### HTTP node The HTTP request node is how a scenario talks to the outside world. Everything else on the canvas either gets data ready for it, or works with what it brought back. Method The method has to match what the other side expects. If you get it wrong, the request fails even though the URL is perfect, and that is the first thing worth checking when something does not work. Integrations often use different methods at different steps, so check each request on its own. GET asks for something. Parameters go in the URL and there is no body. You use it for status checks and validations. POST submits something new. The data goes in the body. This is how leads are sent. PUT replaces a whole record. PATCH changes only part of one. DELETE removes a record. With leads that usually means a cancellation. HEAD asks only for the headers. Handy when you just want to know whether the endpoint is alive. OPTIONS asks what the endpoint supports. You will rarely need it. Endpoint The URL the request goes to. Rather than typing the full URL into every request, store the base as a parameter and write {endpoint}/register-lead. Then you have one place to change it when the advertiser moves their API, and you can point everything at a sandbox by swapping a single value. If you put query parameters straight into the URL, they are kept. PalDock merges them with anything you add in the query list, so you can use whichever is more convenient. Pingtree type You only need this when the integration runs in a pingtree. It tells PalDock whether this request is the ping, the post, or the post verification. Leave it empty and PalDock treats the flow as a post. That is fine while the integration has one flow. As soon as you want a second Start node on the canvas, both need a type, otherwise PalDock cannot tell which one to run. Format The format decides how the body is packaged. The other side accepts one and rejects everything else, so read their documentation instead of guessing. JSON sends an object in the body. Most modern APIs want this. form-data uses multipart encoding, typically for file uploads. x-www-form-urlencoded sends key=value pairs joined with &. Older APIs often want this. x-www-form-urlencoded + JSON is a hybrid: parameters are URL encoded, but a field can still carry JSON. login-pass-data sends credentials alongside the data, for APIs that do not use tokens. This setting covers the whole request. Individual fields can still be nested inside it, and Field format explains how. What goes in the request Query parameters are added to the URL. They are usual for GET, but they work with any method. Headers carry everything around the data: content type, authorisation, and whatever custom keys the API asks for. Body is the payload itself, for POST, PUT and PATCH. Every value is a plain text field. You type what you need and use the picker to drop in a reference, which shows up as a tag but is stored in braces, like {data_first_name}. You can mix the two, so Bearer {token} and {first_name} {last_name} both work. PalDock adds User-Agent: CC/2.0 and Accept: application/json on its own. If you set either of them yourself, yours is used instead. Empty and missing values Some APIs care about the difference between an empty string, a null, and a field that is not there at all, and they will reject the request if they get the wrong one. Two settings handle it, and both apply to the query and the body. Convert blank values changes the value before it goes out: empty string to null null to empty string missing to null missing to empty string empty string or missing to null null or missing to empty string Skip field when drops the field from the request altogether: null empty string missing null or empty string missing or empty string null or missing null, missing or empty string The difference is what actually arrives. Convert sends a different value, Skip sends nothing. When an API rejects a null but is perfectly happy if the field is not there, Skip is what you want. Parser The parser decides how the response is read. Choose JSON or XML and PalDock turns the response into something you can address field by field, like {parsedBody.leadId}. Anything else is left as plain text, and {parsedBody} stays empty. If you leave the parser alone, PalDock goes by the content type the other side declared. Set it yourself when they declare the wrong one, which happens more often than you would expect with older APIs that return JSON but label it as HTML. Watch out for this one, because it fails quietly. The request goes through, the status is 200, and every condition reading {parsedBody.something} finds nothing at all. If your conditions behave as though the response were empty, look here first. Insecure PalDock normally checks the certificate of the server it is calling, and refuses to send anything if the certificate is expired, self signed, or belongs to a different host. Turning on insecure skips that check. It is there for a partner’s test environment with a self signed certificate. On production it means you no longer know for certain who is receiving your lead data, so use it to get unblocked and then ask them to fix the certificate. Timeout The timeout is how long the request waits for an answer before giving up. It is a ceiling, not a delay, so if the answer comes back in half a second, the flow carries on in half a second. Keep it short inside a Structure, because the customer is sitting in front of the form the whole time. There are also limits on the node, the run and the scenario above this one. See Limits and timeouts. Authentication There is no separate authentication node. Credentials go into the request like any other value, usually as a header. A static token or API key is the easy case. Store it as a parameter and use it: Authorization: Bearer {token} X-Api-Key: {token} Basic auth takes one more step, because the header carries a single encoded string rather than two values: A Set node joins them, for example {auth0} = {client_id}:{client_secret}. A Modify Field node runs to-base64 on it and writes the result into {auth}. The header then reads Authorization: Basic {auth}. A token you have to fetch, as with OAuth or JWT, needs its own request before the real one: An HTTP node calls the token endpoint. These endpoints usually want x-www-form-urlencoded with grant_type in the body, and are themselves protected by Basic auth as above. The connection leaving that node checks that a token actually came back, for example that {parsedBody.access_token} is not empty. Skip this and the flow carries on with an empty token, and every request after it fails for reasons that make no sense. A Set node stores it as {token}. Everything after that sends Authorization: Bearer {token}. That auth call is a normal node, so it takes its own time and counts against the limits. If several requests in one flow would each fetch the same token, fetch it once at the start instead. Signature When the other side wants signed requests, use the Signature setting rather than building the signature by hand. PalDock covers MD5, HMAC, Digest and HTTP Signatures through presets. See Signature. What you get back Everything the request produced is available to the nodes after it: {status} is the HTTP status code. {parsedBody} is the parsed response, addressed with dots, as in {parsedBody.offers.0.offerId}. {body} is the raw response as text, whether it parsed or not. {headers} are the response headers. {uri} is the URL that was called. {query}, {request_body} and {request_headers} are what PalDock actually sent. Those last three are the ones to reach for when a request is rejected and you cannot work out why. They show what really left PalDock, rather than what you meant to configure. Before and after Before the request, use Modify to get values into the shape the other side wants. Doing it there instead of inline means that when a value arrives wrong, you can see where it came from. After the request, put conditions on the connections leaving the node to work out what the response means, and use Set to keep what you need, usually {external_id} and {redirect_url}. Common mistakes The wrong method with the right URL. The wrong format with the right method and URL. Treating any 2xx as acceptance. Most rejections arrive with a perfectly normal status code. The wrong parser, so every condition reads an empty body and nothing ever matches. No check that the token request actually returned a token. The base URL typed into every request instead of stored as a parameter. #### HTTP Signature Some partners want every request signed. The signature proves two things: that the request came from you, and that nobody changed it on the way. They compute the same signature on their side and compare. PalDock does the signing. You choose a preset that matches what the partner’s documentation describes, and PalDock builds the signature from the request as it is being sent. Presets are fixed and you cannot write your own signing rule. If a partner needs one we do not have yet, tell us and we will add it. The settings Preset decides what gets signed and how. Hash is SHA-256 or SHA-512. The partner will say which. MD5 presets do not have this choice. Delimiter is the character used to join values before hashing, either |, & or .. Only presets that join values need it, and the partner’s example will show you which one they use. Position decides whether your secret goes before the data or after it. Prefix puts it first, suffix puts it last. MD5 presets need this, and the partner’s example is the only way to tell which they expect. Secrets Store the signing credentials as parameters in the integration: sign_secret is the shared secret. Every MD5 and HMAC preset needs it. sign_keyid is the key identifier that goes into the signature header. Only HSIG needs it. If one is missing when the request runs, the node fails and the log says which. Where the signature ends up This is the step people miss, and the failure is silent. MD5 presets add it to the body themselves. A signature field appears in the payload. You do nothing. Every other preset gives you tags and you place them in the headers yourself: {signature} is the signature {digest} is the digest, where the preset makes one {timestamp_sign} is the timestamp that was signed {random_sign} is the nonce, for the preset that uses one If the partner asks for the signature in X-Signature, you add that header with {signature} as its value. Forget it and the request goes out unsigned, which the partner usually answers with a bare 401. When a preset signs a timestamp, PalDock also adds a Timestamp header on its own, so what it signed and what the partner sees are always the same value. A complete example The partner’s documentation says: sign the raw JSON body with HMAC SHA-256 and send it in X-Signature. In the request: Method: POST Endpoint: {endpoint}/leads Format: JSON Body: first_name {first_name} last_name {last_name} email {email} In the headers: X-Signature: {signature} In the Signature card: Preset: HMAC · Body Hash: SHA-256 Delimiter: | And in the integration parameters: sign_secret: the key they gave you That is everything. PalDock builds the body, signs it, and replaces {signature} in the header before the request leaves. Picking the preset Look for these phrases in the partner’s documentation: “signature from the request body” is HMAC · Body “HMAC(timestamp + body)” or anything about replay protection is HMAC · Unix Timestamp + Body a date header in HTTP format, like Tue, 11 Aug 2026 10:00:00 GMT, is HMAC · RFC 7231 Date + Body “sign the JSON exactly as sent”, with a timestamp, is HMAC · Unix Timestamp + JSON Body “parameters sorted alphabetically”, or an example with sorted keys, is HMAC · Params A→Z a nonce alongside the timestamp, method and path is HMAC · Params A→Z + Nonce + Body Hash “send a Digest header”, or Digest: SHA-256=…, is Digest · Body (Base64) “HTTP Signatures”, “Authorization: Signature”, “signed headers”, or (request-target) is HSIG + Digest an MD5 example, or a hash of joined values with a secret, is one of the MD5 presets Other terms worth searching their docs for: canonical string, X-Signature, Base64, nonce, SHA-256, SHA-512. MD5 presets These join the body into one string, add your secret, and hash the result with MD5. They differ in how that string is built. Values takes only the values: value1|value2|value3|secret Key=Value takes the field names too: first_name=John&last_name=Doe&secret As-sent keeps the order from the request editor. A→Z sorts by field name first. If the partner’s example shows the fields in alphabetical order, you want A→Z. Where the secret sits is set separately, with Position. The two examples above both put it at the end, which is the common case, but some partners expect it at the front. Nested fields are flattened to their dotted names first, so customer.name is signed as customer.name. The presets: MD5 · Values · As-sent MD5 · Values · A→Z MD5 · Key=Value · As-sent MD5 · Key=Value · A→Z HMAC presets These sign with your secret, which is what makes them stronger than a plain hash. They differ in what exactly they sign. HMAC · Body signs the body values joined with the delimiter. HMAC · Unix Timestamp + Body puts a Unix timestamp in front, so an intercepted request cannot be replayed later. HMAC · RFC 7231 Date + Body is the same, with the timestamp written as an HTTP date. HMAC · Unix Timestamp + JSON Body signs the timestamp followed by the body as JSON, rather than joined values. Use it when the partner signs the exact JSON they receive. HMAC · Params A→Z sorts the body fields by name and signs them as key=value pairs. Note that this covers the body, not the query. HMAC · Params A→Z + Nonce + Body Hash builds a canonical string from the timestamp, a nonce, the method, the path, the sorted query and a hash of the body, then signs that. Use it when the partner asks for a nonce. Digest Digest · Body (Base64) hashes the body and Base64 encodes it, which is what goes into a Digest header. It needs no secret, because it only proves the body is intact, not who sent it. Partners usually ask for it alongside another signature rather than on its own. HSIG HSIG + Digest (Base64) · SH (TS,H,RT,DIG) NL LC · HMAC is the full HTTP Signatures scheme. PalDock builds a canonical string from four lines, in this order: the request target, the host, the digest and the timestamp. It signs that string and produces a complete header including your key id and the algorithm, ready to place with {signature}. When the request has no body there is no digest, so that line is left out and only the other three are signed. This preset needs both sign_secret and sign_keyid. When it does not work The tag is missing. The signature was calculated and thrown away. Check the headers first. Body signing is byte sensitive. Whitespace, JSON formatting and field order all change the result. If the partner rebuilds the body their own way before checking, the signature will never match, however correct your preset is. This is the hardest one to spot, and the only way through it is to compare the exact bytes with them. The wrong delimiter. The signature is computed, sent, and rejected. There is nothing in the response to tell you it was the delimiter, so if everything else matches their documentation, try the others. The wrong position. Same story. The secret at the front instead of the back gives a completely different hash, and the rejection looks identical either way. The wrong scope. Check whether they sign the body only, or the query as well. Most presets here sign the body. No body. Most presets need one and the node fails without it. #### Import Import lets you create, update, or delete records in bulk from a file instead of one row at a time. The Import button appears in the tables that manage those records. Where import is available Affiliates and advertisers Commission groups Commissions Conversions Offers Tools: structures, integrations, designs, feeds Settings: fields, tags, users How it works Click Import in the table. Download the template. It is offered as CSV or XLSX and contains exactly the columns that table accepts. Fill it in. Upload it back. Choose the mode. Import modes Create: adds new rows. IDs are generated by PalDock. Update: changes existing rows. Every row has to carry an ID. Delete: removes records. Every row has to carry an ID. An update or a delete without an ID has nothing to match against, so the row is refused. Importing conversions Conversions are the one import most workspaces use regularly, and they work differently from the rest. You do not import transactions. Every transaction belongs to a conversion, so you import the conversion and the commission creates the transaction under it. Rows that match no commission are still imported, they simply produce no payout. An imported row is matched the same way a tracking request is: External ID, together with the advertiser ID. The usual pairing. Origin ID or Send ID, when you are pointing at a specific click, lead, or delivery. Conversion ID, for conversions that cannot be addressed any other way. This is the fallback when a row has no external ID and no usable origin. Full detail, including what each row can contain and why a row produced no transaction, is on Manual Tracking and Transaction Import. What to expect An imported conversion behaves like any other from that point on. It counts towards deduplication and recurrence limits, and a later postback can still update it. The result of the import is recorded, so you can see which rows went through and which were refused, and why. #### Lead and Click Capping Capping is configured directly in Filters. You define a maximum number of events, whether that is a click, a lead, a sale or a custom conversion type, within a time window such as per hour or per day. Once the limit is reached, the system stops offering or processing further events according to the filter rules. This gives you controlled delivery and keeps you inside agreed volumes, on links, embedded forms and the API alike. Two places to cap Capping follows the same split as every other filter: On the offer, the cap closes the whole offer for that period. Nothing more comes in. On a channel in the pingtree, the cap closes one advertiser and the lead continues to the others. An advertiser who only wants 200 leads a day belongs on their channel. A budget you cannot exceed belongs on the offer. What the customer sees A capped offer still receives the traffic, it just stops accepting it. Decide what happens to those visitors before the cap is reached, rather than after. With a pingtree, a capped channel is skipped and another one takes the lead, so the customer notices nothing. With a capped offer and no alternative, the lead is refused. See Refuse leads and Process refused leads. Which event to count Capping clicks and capping leads solve different problems. Clicks limit how much traffic arrives, leads limit how much you buy, and sales limit what you owe the advertiser. Capping sales is the closest to a real budget, but it is also the loosest control, because clicks and leads keep costing you effort until a sale finally hits the cap. #### Library of Integrations The Integration Library provides access to a large collection of ready-to-use integrations. Instead of building connections manually, you can add a prebuilt integration to your workspace with just a few clicks. Adding Integrations from the Library Click Add from Library to open a drawer with a searchable list of available integrations. The library includes: Built-in integrations provided by PalDock. Third-party integrations created by external developers and shared through the library. Managed integrations provided and maintained by PalDock. Some integrations may be paid. To unlock them, payment is processed via PalDock credits. When you select an integration, it is added to your workspace exactly as defined in the template. This works as an import of the integration code, including parameters (which will initially be empty). 👉 Important: After adding an integration, you must fill in the required parameters (e.g. tokens, endpoints, credentials) before it can be used. Customization You may freely customize integrations and choose to sync them with the library for updates. Keep in mind that custom changes may conflict with future updates. If conflicts or issues occur, it is up to you to resolve them. Managed Integrations If you do not want to manage integrations yourself, PalDock also offers an Integration Management Service. In this setup: You can add integrations as managed integrations. Your tenant links to these managed integrations using an API token. Managed integrations appear in your workspace with limited editing rights: You cannot delete fields or system parameters, but you can customize them (e.g. provide your own tokens). Requests and core definitions are locked. This approach ensures stability while still allowing minor customization where needed. Scope of Integrations The Integration Library is not limited to advertiser APIs. It also includes other common services, such as: Facebook integrations for tracking. Google Analytics or Google Ads integrations. Email and SMS platforms. Any third-party service exposed through an API. 👉 Tip: Use global fields whenever possible. Prebuilt integrations from the library are designed to map against them, making setup nearly instantly. #### Limits and timeouts PalDock applies several limits at the same time so that no flow can run forever or block the system. Most of them you will never reach. This page lists them all in one place, so you know where to look when a run stops earlier than expected. Timeouts you set yourself Only two limits are yours to set, both on a node: HTTP request timeout, on an HTTP node. How long the node waits for the external server to answer. Webhook waiting time, on a Webhook node. How long the flow waits for an external system to call back. Everything below is a system limit. System timeouts Node: 5 minutes for one node from start to finish. Connection: 1 minute to evaluate an arrow and hand over to the next node. Scenario run: 250 minutes for the whole run, across all nodes and branches. Synchronous run: 50 seconds for a scenario that runs while someone is waiting for the answer. Webhook waiting inline: up to 40 seconds, when the node blocks the flow. Webhook waiting in the background: up to 48 hours, when the flow is released and resumed later. Webhook data: kept for 180 days after it arrives. The synchronous limit is the one that matters in practice. Form validation, autocomplete and leads sent over the API all run while a visitor or an API caller waits, so the whole flow has to finish inside it, not just one node. Size limits A scenario can have up to 50 nodes. A single node can run at most 30 times within one run. A loop without a Breaker ends here, with the run stopped and an error in the log, so give every loop a Breaker that ends it sooner and on your terms. The limit of 30 is what protects you from a loop created by accident. If a node would run more often, the run is stopped and an error is written to the log. A Breaker node lets you set a lower limit yourself. Retries A node runs once. There is no automatic retry, and a failed node does not repeat on its own. If you need a second attempt, build it into the flow with a condition on the response. What happens when a limit is reached The run stops at that point and the reason is written to the run log. Branches that already finished keep their result. Nothing is retried silently. Business limits The limits above are technical. Volume limits, such as how many leads or clicks an offer may take per hour or per day, are configured separately. See Lead and Click Capping. #### List of modifications Modify Field transforms a value before it is stored or sent on. Reformatting a date, translating your vocabulary into the advertiser’s, deriving one field from another, or dropping a field from the request entirely. It is used in Structures, in integrations, and in tracking. The operations are the same everywhere. How a modification is built Each modification targets one field and is made of steps. A step has four parts: Source, where the value comes from: this field, another field, or the result of an earlier step. Condition, when the step should apply. Use Always when it should apply unconditionally. See Condition Operators and Field value. Operation, what to do with the value. Parameter, what the operation needs, if anything. Some take a pattern, some take a value, some take neither. Steps run in order Steps are executed from top to bottom, and a later step can take an earlier one’s result as its source. That is how you build a value in stages rather than hunting for a single operation that does everything. 1. {nin} first regex match ^\d{2} 2. step 1 prefix 19 The condition on a step is checked against that step’s source value, as it is at that moment, not against what the field held when the modification started. Two ways to use several steps Chained, where each step builds on the last. Good for a single transformation with stages. Independent, where several steps read the same original value and only one of them matches. Good for mapping a list of values, since each step has its own condition and only the matching one fires. If you need several genuinely separate transformations of the same input, it is usually cleaner to create a helper field for each, then combine them at the end. That keeps each chain short enough to follow. The operations Changing the type to-int, to-float, to-bool, to-string Text prefix and postfix add something to the front or the back replace set the value for a fixed one regex-replace rewrites part of it by pattern first-regex-match pulls out the first match Dates format-date changes how a date is written modify-date shifts it forwards or backwards unix turns it into a timestamp Encoding to-base64 and from-base64 urlencode and urldecode Calculating math evaluates an expression, using {value} for the current value Not sending do-not-send removes the field from the request Getting it right Test with real data, not with what you expect the data to look like. Most Modify Field problems are not wrong logic, they are a value that arrived in a shape nobody planned for. Keep chains short. Three steps you can read beats one clever step you cannot. #### List of nodes A node is one action on the canvas. Nodes are joined by connections, which decide what runs next and can carry conditions, so the flow branches on the result. Different parts of PalDock use slightly customised versions of the Connection Creator, but the node types below are the same everywhere. Start and End Every scenario begins with a Start node and every path should reach an End node. The Start node has a flow, which decides what triggers the scenario. In integrations there are two, Ping and Post, and each is a separate path with its own Start and its own End. Everywhere else there is one. A scenario can also be started by an internal event, such as a conversion or a status change, or by an external system calling in through a Webhook node. The End node records the outcome. Marked success, the lead goes through. Marked failed, it does not. See Where Connection Creator is used. Working with data Modify changes the value of one or more fields, with conditions inside the node. This is where you translate your values into whatever the other side expects. Set stores a value from a response so it can be used later in the flow, or after it. Set Event records an event. For example, when a response comes back as a duplicate, increment the Duplicate counter by one so it shows up in reporting. Mirror inherits all settings from another node, so you maintain one master and the copies follow it. Flow control Wait pauses the flow before it continues. It can wait a fixed time, until a specific date and time, until a given hour of the day, until the next working day, or a set time after an event. Breaker limits how many times a loop may repeat, so a retry cannot run forever. There is no node that repeats something on its own. You build a loop from a Breaker, a Wait and a connection leading back to an earlier node. The Breaker is what caps it. SubScenario calls another scenario from this one and exchanges data with it, which keeps shared logic in one place instead of copied across integrations. Requests HTTP node sends a request to an external service. You set the method, endpoint, query, headers and body, plus the format, the timeout and, where required, a signature. Authentication is part of this node, not a node of its own. API keys, Basic auth, OAuth and client certificates are all configured here, and an access token can be stored and refreshed. Webhook waits for an external system to call in. The flow pauses at the node and continues when the call arrives, which is usually better than polling when the other side supports it. Related, but not nodes Connections join nodes and carry the conditions. See Connections with Conditions. Keys hold the tokens, endpoints and custom parameters an integration uses. Structures define the fields a scenario works with. #### Local, Global and Custom fields Local, Global and Custom fields Fields define what can be collected in a form and what travels onwards with the lead. PalDock has three levels of them, and the difference is who defines them and how widely they apply. Global fields are defined by PalDock and exist in every workspace. Local fields are defined by an admin and exist in one workspace. Custom fields are defined inside one structure and exist only there. Use global fields wherever you can This is the one recommendation worth taking from this page. Integrations from the library work immediately. They are built against global fields, so an integration you add from the library can be ready as soon as you fill in a token, instead of after an hour of mapping. Every advertiser you add later is the same. Leads move between workspaces without mapping. When you send a lead to another PalDock workspace and both sides use global fields, the fields line up on their own. With custom fields, someone has to map them by hand, on both sides, and again whenever either side changes something. Reporting stays comparable. Email exports into the same column no matter which form or workspace the lead came from. Your partners save the same work you do. A structure built on global fields is one an affiliate or an advertiser can connect to without asking you what each field means. The cost of not doing it is not one big decision. It is a small amount of mapping repeated in every integration, every export and every new partner, for as long as the workspace exists. So use a global field wherever one fits, a local field when none does, and a custom field only for something genuinely one off. Global fields Global fields are the same in every PalDock workspace: same system name, same type, same meaning. First name, last name, email, phone, address, and many more. Because they are the same everywhere, nobody has to map them. That is what makes the library and cross-workspace delivery work. Some of them belong to the person, not to you. First name, last name and email are linked to the user’s account, which spans every workspace they have access to. When the user changes their name, it changes everywhere, and an admin cannot change it for them. That is deliberate: the same person should not be called two different things in two workspaces. This applies to the fields tied to the account. A global field describing a lead, such as an amount or a product, behaves like any other field. Global fields use the g_ prefix, so a global email is g_email. The prefix is reserved and nothing else in the workspace can use it. It also replaces the data_ prefix that fields defined in a structure carry, so in a scenario a global field is written as {g_email}, not {data_g_email}. You cannot edit a global field. If you need one that behaves differently, make a local field instead, and accept that it will not be linked to the account. Local fields Local fields are yours. You define them once in the workspace and reuse them across every structure, instead of building the same field again in each form. They are for what global fields do not cover, and for anything specific to how you work. They can be edited and customised freely. Once created, they appear in a list and can be picked in any structure. When you use one in a structure, PalDock applies the prefix and locks the field name, so the same field cannot drift into two spellings. A local field can still be modified inside a particular structure, so one structure can format it differently while the definition stays shared. The structure shows an icon when that is happening. Custom fields Custom fields live inside a single structure and nowhere else. They are fully editable and quick to make, which is exactly why they multiply. Before making one, check whether a global field already covers it and whether a local field would serve the next form too. Use them for what is genuinely unique to one form. Creating a field In a structure, click Add and the field is created as a custom field, ready to use immediately. In the workspace, open the local fields section in Settings and click Add. This is the full editor, the same as in a structure. You can also create a local field without leaving a structure: pick the local option and click Add. It is a shorter form, and the new field appears in the list of local fields straight away, ready for every other structure. Using a local or global field in a structure Instead of adding a new field, click the selection icon, the dashed square next to the field name. A panel opens with everything available, and you can search it by typing. Choose one and the field name is filled in and locked, with the prefix applied. The structure then shows visually that this is a shared field rather than a custom one. Picking a predefined field is never compulsory. It is just usually the better choice. The list of global fields These are the global fields available in every workspace. Use the system name in structures and integrations. The person name_first : first name name_last : last name nickname : nickname email : email address phone_prefix : international dialling prefix phone : phone number without the prefix phone_full : the whole number including the prefix birth_date : date of birth age : age gender : gender nationality : nationality language : language marital_status : marital status education : level of education id_national_number : national identification number id_card_number : identity card number id_vehicle : vehicle registration plate Household household_members : how many people live in the household household_members_adults : how many adult people live in the household household_children : how many of them are children household_members_income : the household’s combined income Address address : the whole address in one field address_street : street address_street_number : street number address_city : city address_zip : postal code address_state : region address_country : country Contact address Use these when the contact address differs from the main one. address_contact_status : a checkbox saying the contact address is different address_contact : the whole contact address in one field address_contact_street : street address_contact_street_number : street number address_contact_city : city address_contact_zip : postal code address_contact_state : region address_contact_country : country Company company_name : company name company_registration : registration number company_vat : VAT number company_address : the whole company address in one field company_street : street company_street_number : street number company_city : city company_zip : postal code company_state : region company_country : country company_invoicing_email : invoicing email Bank bank_account_number : account number bank_account_code : bank code bank_account_prefix : prefix of account number bank_account_full : the whole account in one field bank_iban : IBAN bank_swift_bic : SWIFT or BIC bank_name : bank name bank_address : bank address Employment and income employ_type : type of employment employ_position : job position employ_time : how long they have been employed employer_name : employer name employer_address : employer address fin_type : type of income fin_income : income fin_income_gross : gross income fin_expenses : expenses fin_expenses_credit : any expenses related to credit The product amount : amount of the product price : price quantity : quantity currency : currency discount : discount amount coupon : coupon code purpose : what the product or service is for period : duration period_sub : a second duration, when the product needs one period_unit : the unit of the duration, such as day or month period_start : start date period_end : end date home_type : housing classification Items For products with more than one line, following the structure used by analytics platforms. item : the list of items item_id : item ID item_name : item name item_brand : brand item_variant : variant item_category through item_category5 : up to five levels of category item_list_id : list ID item_list_name : list name Assets asset : the list of assets asset_type : what kind of asset it is asset_status : its status asset_variant : its variant asset_value : its value asset_unit : the unit the value is in asset_year : the year of pruchase asset_usage : anything about possible usage Consents consent_processing : consent with data processing consent_marketing : consent with marketing Other domains : websites type : a type of any kind status : a status of any kind quality : a quality of any kind consumption : a consumption of any kind notes : a free note Missing something The list grows over time. If you keep building the same local field in every workspace, or an advertiser keeps asking for something that is not here, tell us. When it is common enough to be useful to others, we will add it as a global field, and everyone stops mapping it by hand. #### Logs Logs are the complete record of what happened in your workspace, and the first place to look when something did not go the way you expected. Where a report tells you how many, a log tells you which one and why. There are five kinds: Clicks Leads Conversions Integration requests Tracking requests They all behave like any other table in PalDock. The same filters, columns, and export apply, and partners see only their own rows. State Every entry carries a state. OK means it was processed. Failed means it was not, usually because it did not pass validation. A failed entry is normally discarded, unless Refuse leads is enabled, in which case it is kept. State is the coarse answer. The status underneath it says what actually happened. Lead statuses Accepted: the lead was received and is on its way Processing: at least one channel is still working on it. The detail lists the channels and what each is doing, such as waiting, bidding, or verifying Sold: at least one channel bought the lead. The detail lists which ones, for how much, and where the customer was sent Not sold: every channel had its turn and none took it. The detail lists each channel and why, which is where the reject reasons from your integrations show up Refused by Validation: the lead passed the structure but failed an external check, such as a phone or bank account validation. The detail names the field and the check Refused by Filters: the lead was stopped by an offer filter before it reached any channel Refused by Pingtree: the lead went into the pingtree and came out unsold Error: something broke rather than said no. A timeout, a 5xx from an advertiser, or an error inside the pingtree Invalid data: the lead was rejected on arrival. The detail names the field and what was wrong: a required field missing, a value that is not one of the allowed options, or a value that does not match the required format Not allowed: the affiliate is not permitted to send to this offer No destination: there was nowhere to send it. No active channel, no pingtree, or no offer link Duplicate: the advertiser already has this lead Sold and processing together These two can appear at once, and only these two. When one channel has bought the lead while another is still working, the status is Sold and the detail shows both. Not sold never appears alongside them, because it is only decided once every channel has finished. Click statuses Accepted: the click was recorded and the visitor was redirected. The detail includes the URL, worth checking when the visitor ended up somewhere unexpected, since a redirect can come from a cap or a rule rather than the offer’s own link Invalid data: a required parameter was missing or malformed Bot: the click was identified as not coming from a person Not allowed: the affiliate is not permitted to send to this offer No destination: no offer link, an inactive offer, or a cap that has been reached Refused by Filters: the click was filtered out The detail The detail column is where the reason lives. For anything involving channels it is a list, one entry per channel, so you can see that Channel A paid, Channel B said the person was a duplicate, and Channel C timed out. That is what makes it worth reading rather than glancing at. The status tells you the outcome, the detail tells you why, and with several channels the answer is different for each one. Conversion logs The conversion log is where you go when a conversion exists but no transaction came out of it. Some conversions succeed and produce a transaction, others do not, for example because they were deduplicated on the advertiser’s external ID. The log tells you which happened. Every step of a conversion’s life is recorded: created, and created as a child of another conversion updated redirected sent into the pingtree, and what the pingtree answered what an advertiser answered every incoming postback, and every Tracking API call sent out Each entry has a severity, so you can tell an ordinary event from a warning and from a genuine error. For the full list of reasons a conversion produced no transaction, see Tracking and Conversion Logs. When the conversion itself is fine, the cause is on the commission side. See How PalDock picks a commission. Tracking logs Tracking requests carry a result on top of the state, saying whether the request was processed, how it was handled, or why it was refused. The full list of results and what to do about each is on Tracking errors and reasons. The one you will meet most often is Unmatched: the request arrived and was valid, but PalDock could not tie it to any conversion. That almost always means the identifier the advertiser sent is not the one you stored. Start with Tracking processing and check that {external_id} is being stored by your integration. Integration logs Every run of an integration is logged node by node, with the data each node received and returned. This is a different level of detail from the lead log. The lead log tells you the lead was not sold, the integration log tells you which request failed and what came back. See Connection Creator. Which log to open A lead or a click did not do what you expected: the lead or click log. Read the status, then the detail. A specific request failed against an advertiser: the integration log. A conversion was recorded but there is no payout: the conversion log. A postback or pixel seems to have done nothing: the tracking log. #### Manual Tracking and Transaction Import Manual import is the fallback when no automated method is available: an advertiser who cannot implement a pixel or a postback, a batch that arrived by email, or a correction after something went wrong. Import is in Reports, Transactions. What an import does An imported row behaves exactly like a tracking request, so it can do two things. Create: a new conversion is recorded. Commissions run on it and produce transactions. Update: an existing conversion is changed, typically to set the result or the value. The transactions under it are updated. You do not create transactions directly. You import the conversion, and the commission creates the transaction under it. Rows that match no commission are still imported, they just produce no payout. Before you start Make sure the commissions are set up and active for the conversion type you are importing. Decide which identifier each row will carry. Without one, nothing can be matched. Download the template and test with a few rows before importing a large batch. What each row can contain Origin ID: links the row to the original click or lead. External ID: the advertiser’s own order ID. Needed for deduplication and for updating later. Conversion date (optional): the date the conversion happened. Without it, the current date is used. Result (optional): pending, approved, or rejected, applied to the transaction. An update needs to point at exactly one conversion. When several conversions exist under the same origin, the Origin ID alone is not enough and you have to send the external ID as well. See Conversion IDs explained. What happens after the upload Each row goes through the same steps as a postback or a pixel request. The conversion is recorded or found. Deduplication on the advertiser’s external ID applies. A row for an order that already exists is stored as a duplicate and produces nothing. Commissions run, with their conditions, active periods, and recurrence limits. Matching rows produce transactions, which appear in the transaction report. Nothing about an imported conversion is treated differently later. A postback can still update it, and it counts towards recurrence limits and deduplication like any other. When rows produce no transaction Check the conversion log first, then work through the usual causes: No commission matches that conversion type. The commission is inactive or outside its active period. The recurrence limit was already reached. The row was deduplicated on the external ID. The row was an update that found no conversion to update. See Tracking errors and reasons. #### math The math operation calculates a value from a formula. You write the expression, PalDock fills in the field values and works out the result. This operation was previously called match, which was a typo. How it works Write the formula in the parameter. Reference field values in braces: {value} is the value the step is working with. {field_name} is any other field in the scenario. Formula: {value} * 2 Input: 30 Result: 60 Formula: {price} / 100 Input: 19900 Result: 199 You can combine several fields in one formula, for example {length} * {width}. What you can write Operators + addition - subtraction * multiplication / division ^ exponentiation ( ) parentheses, to control what is calculated first Functions sqrt(x) square root abs(x) absolute value round(x) round to the nearest whole number floor(x) round down ceil(x) round up log(x) natural logarithm sin(x) and cos(x) When the calculation fails If the formula cannot be worked out, the field keeps its original value. Nothing is written to the log, no error is raised, and the flow carries on. That makes a broken formula genuinely hard to spot, because the value that arrives at the advertiser looks plausible, it is just the number from before the calculation. A field of 19900 that should have become 199 still reads as an amount. The usual causes are an empty input field, a value that is text rather than a number, and a reference to a field that does not exist in this scenario, which leaves the braces unreplaced. So check the input before you calculate. Convert with to-float or to-int first, and put a condition on the step so it only runs when the field actually holds a number. Rounding Division produces decimals, and most advertisers will not thank you for 66.66666666666667. Wrap the formula in round(), floor() or ceil() depending on what the value means. Rounding down is the safe choice for anything the advertiser will treat as a limit, since rounding up can push you over it. Settings The operation takes one parameter: the formula. Everything else is the source and the condition. Reference Calculations are performed by chriskonnertz/string-calc, which is where the full list of supported functions lives. #### Mirror The Mirror element allows you to reuse the configuration of another element without duplicating it. A Mirror inherits all settings from a selected “master” element. Any changes made to the master are automatically applied to all its mirrors. The mirror itself cannot be modified – you can only switch it to point to a different parent element. This is useful when the same request or configuration must be used in multiple places, but you want to maintain it in a single location. This approach reduces duplication and ensures consistency across integrations. #### Modification A Modify scenario fills or changes the value of a field while the form is being filled in. Instead of relying only on what the user types, PalDock can write a value into a field based on other fields, or fetch it from an external service. Modify is a scenario attached to a field. It is not the same thing as the Modify node, which is one element inside a scenario. A Modify scenario often contains a Modify node, but it does not have to, and a Modify node can be used in any scenario, not only this one. The field being filled is usually hidden, but it does not have to be. This feature is especially useful when you want to: Keep forms shorter and simpler for users, while still capturing all required data. Add extra business context without manual input. How Modify works A field can be set to fill automatically when another field is completed and the form is submitted. For example, entering a company ID may trigger an API call that fills in the company name, address, and postal code into their respective fields without the user needing to fill them up manually. This is done through Connection Creator, where you build the scenario and connect it to specific input and output fields. Examples include: Looking up company details from a business registry. Retrieving mobile carrier. Completing address details based on ZIP code. And many others. More than one scenario on a field A field can have several Modify scenarios, and they run in the order you set. Use this when the value is built in steps, for example one scenario fetches the company record and a second one formats the address it returned. The order matters. A scenario that reads a value another scenario has not written yet will find the field empty. Changing a value you already have Not every Modify needs an external service. When the value is already in the form and only needs reformatting, trimming, or combining with another field, use the Modify node’s operations instead of an HTTP request. That keeps the form fast, because nothing has to wait for a third party. See List of modifications for what the operations can do. What to watch out for ⚠️ Modify through an external service can break the entire system if it is set up incorrectly, preventing the form from being processed and the lead from being sent to offer. External service outage. If the service is unavailable, the form can be submitted, but cannot be processed until a valid response is received. To avoid this, configure a fallback response for the failure case, for example on status codes 4xx or 5xx, so the scenario finishes even when no value was filled. Timeouts. If an external service takes too long to respond, users are stuck waiting with a loading spinner until the request finishes. This creates a poor user experience and increases the risk of abandonment. Set the timeout on the HTTP node, and keep in mind that the whole scenario runs while the visitor waits, so it has to finish inside the synchronous limit. See Limits and timeouts. Combination with validation. If Modify from an external service fails, the field will not be populated. If validation is also enabled on that field, it will fail as well, preventing the form from being submitted. Both features must be configured correctly with this risk in mind. #### Modify in Connection Creator Advertisers rarely accept your data as it is. A phone number needs a prefix, a date needs a different format, your full-time has to become their employed. The Modify Field node is where that happens. Put it before the request, not inside it. Building values in the HTTP node works, but when something arrives wrong at the other end you have nowhere to look. Keeping the transformation in its own node means you can open the run and see exactly what went in and what came out. How the node is organised One node holds as many sections as you need, and each section is one target field. Inside a section you define what happens to that field: Source, where the value comes from. Usually the field itself, but it can be another field, or the result of an earlier step in the same section. Condition, when the change should apply. Use Always when it should always happen. See Condition Operators and Field value. Modification, what to do with the value. See Modify Field for the full list of operations. Output, the result, for operations that need one. A section can hold several of these. That is how you map a list of values: one line per value, all in the same section, each with its own condition. Field: {income_type} equals full-time → employed equals self-employed → self-employed equals pension → pensioner One node, one place to look, instead of a branch per value. Order fallbacks deliberately Modify Field processes the lines in a section from top to bottom. Each later line works with the value as it exists at that point, so the position of a fallback matters. If the fallback is unconditional, or its condition would still match a value produced by an earlier rule, put it first. The more specific rules can then override it. Field: {income_type} 1. fallback → other 2. equals full-time → employed 3. equals self-employed → self-employed Do not put that kind of fallback last. It would also run after a successful mapping and could replace the mapped value. A fallback can go last when its condition identifies values that are still unmodified. This can be cleaner than explicitly listing every value that should not match the fallback. Field: {data_bank_code} 1. 2010 → 1 2. 0100 → 3 … last: matches ^\d{4}$ → 1 Here, a known code such as 2010 becomes 1, so it no longer matches ^\d{4}$. An unknown code such as 9999 remains unchanged, still matches the final rule, and receives the fallback value. The important rule is not that a fallback must always be first or last. Place it so that its condition cannot match and overwrite a value that was already transformed successfully. Building a value in steps The lines in a section run in order, and a later line can take the output of an earlier one as its source. That is how you build a value in stages instead of looking for one operation that does everything. Field: {created_date} 1. source: {created_date} modify date → +30 days 2. source: step 1 format date → d.m.Y The second line formats the date the first line produced. Pick the earlier step in the Source setting, the same way you would pick a field. Keep this in mind when writing conditions. A condition on the second line is checked against whatever that line’s source holds at that moment, which may no longer be what the field contained when the node started. Common uses Translating values. Their vocabulary instead of yours, as above. Keeping a number within the advertiser’s range. A numeric field can carry a value the advertiser will not accept. If they lend up to 20 000 and your form allows more, replace anything above that with 20 000, so the request goes through with the highest amount they can actually work with. This is about the value in one field, not about how many leads an advertiser receives. For that, see Lead and Click Capping. Filling empty required fields. Some advertisers reject a request outright when a field is missing, even one they do not care about. Put a placeholder in. Reformatting. Prefixes, date formats, splitting or joining values. Leaving a field out entirely. Sometimes an empty value is worse than no value. Use do-not-send to drop the field from the request instead of sending it blank. Watch the braces A reference goes in braces, as {parsedBody.name}. Written without them it is a plain string, so a condition can never match it and the whole section silently does nothing. This is the most common reason a Modify Field node appears to be ignored. #### modify-date The modify-date operation shifts a date forwards or backwards. You describe the change in words and the operation works out the new date. The result always comes back in ISO 8601 format, such as 2024-02-22T15:30:00+00:00, whatever format went in. How it works You write the shift in the parameter, in plain English. Value: 2024-02-21 15:30:00 Change: +1 day Result: 2024-02-22T15:30:00+00:00 Value: 2024-02-21 Change: -2 months Result: 2023-12-21T00:00:00+00:00 Value: 2024-02-21 Change: next Monday Result: 2024-02-26T00:00:00+00:00 Common forms are +30 days, -2 hours, +1 month, next Monday, last day of this month. PHP understands a lot more than that, and the reference at the bottom has the full list. Using another field in the shift The change does not have to be fixed. Put a field reference in braces and it is filled in before the date is worked out. Change: +{period} days That is how you build an expiry date from a term the customer chose, rather than writing a separate step for every possible length. The output format is not optional The result is always ISO 8601. If the advertiser wants something else, follow this step with format-date. That is the usual pair: shift the date, then write it the way they asked for. An unreadable date stops the flow If the value cannot be read as a date, the node fails with an error and the branch stops there. Put a condition on the step so it only runs when the field holds something. An empty date field is the most common cause by a distance. Careful with months Adding a month is not the same as adding thirty days, and the difference shows up at the end of a month. 31 January plus one month lands in March, because February has no 31st and the overflow carries forward. If you mean a fixed number of days, say days. Use months only when the advertiser’s rule is genuinely expressed in months. Working with the other date operations modify-date shifts a date format-date writes it a different way unix turns it into a number Shift first, then convert or format. Doing it the other way round usually means the shift runs on text that is no longer a date. Reference See PHP: DateTime::modify and Relative Date and Time Formats for everything the change accepts. #### Multiple Commissions for the Same Conversion Type If multiple commissions exist for the same conversion type, the behavior depends on how the transaction is created. When a transaction is created automatically by the system based on commission rules, all commissions whose conditions are met will be triggered. When a transaction is created through Tracking Pixel or Postback, only one commission is selected, using this priority: Based on received Commission ID The first commission (based on order) matching the provided Type, if Commission ID is not provided The first commission (based on order) in the list based on weight order, if neither Commission ID nor Type is provided The default commission is always the first one in the commission list, but you can reorder commissions at any time using drag and drop. #### Multiple Structures for Offers and Integrations An Offer can have more than one structure. You do not need a separate offer, or a separate integration, for every form. Why this exists You often have several structures that are almost the same. Two products, two landing pages, and the only difference is a single field. Copying the whole structure, and then maintaining both copies with all their modifications, is slow and easy to get wrong. For when a second structure is the right answer and when it is not, see Form structure. How structures reach an integration Structures are attached to the offer. Integrations are added to the offer through its pingtree. So an integration works with whatever structures its offer has, without being linked to them itself. When you map fields in that integration, you see the fields from all of the offer’s structures, deduplicated by name. You map each one once and it works for every structure. Matching is by name only PalDock matches fields by system name. A lead always arrives from exactly one structure. When the integration builds its request, it looks up a field by its system name and takes whatever value that lead carried. It never asks which structure the lead came from. The field type plays no part in this. An integration does not see whether a field is text, a number or a dropdown, and cannot work with that information. It only sees the name and the value. This also means two structures can define the same system name with different field types and the integration will not notice. It takes the value it finds. Whether that is a problem depends on what the advertiser does with it. What you need to keep true This works only while the names stay consistent. Two rules: The same meaning must have the same system name in every structure on the offer. If one calls it phone and another phone_number, the integration sees two different fields and one of them will always be empty. The same system name must always mean the same thing. If id is a customer number in one structure and a product code in another, the integration will send the wrong value and nothing will warn you. Use global fields wherever you can. Their system names are managed centrally, which is exactly what this depends on. Use local or custom fields only for what genuinely differs. When a field is missing from one structure Structures on the same offer are rarely identical, so a mapped field will sometimes have no value. By default it is sent empty. The advertiser receives the key with nothing in it. That is often not what you want, so decide what should happen before you go live: Leave the field out of the request entirely with do-not-send. Fill it with a default value using Modify. Send it empty, if the advertiser accepts that. Example Two landing pages sell the same insurance. Structure A asks for a company ID, Structure B does not. Everything else is identical. Put both structures on the same offer and add the integration to its pingtree. Map the shared fields once. For the company ID, use Modify to decide what happens when it is empty. One offer, one integration, two forms, nothing duplicated. #### Offer Access Defines how visible and available the offer is. It can be set as: public – visible and accessible to all partners private – accessible only if an affiliate requests access and the Admin approves it, or if the Admin adds them manually hidden – not listed in the general catalog and accessible only via direct invitation or link The selected access level determines which partners can see and promote the offer. Changing the level later Partners who already have access keep it. Switching an offer from public to private does not remove anyone, it only stops new partners from taking it without approval. To take access away from someone, remove them from the offer. #### Offer and Pingtree Filters ⚠️ Do not confuse these with report filters. The functionality looks similar, but these filters decide whether a lead is processed at all. Filters can be exported using the code icon (</>) or imported via the + Filter from template button. They work on logical OR and AND conditions and can be grouped or nested for complex setups. Two places, one tool The same filter builder is used in two places, and the only difference is what a failed condition blocks: On the offer. The lead does not enter the offer at all. Nothing further happens to it, and with Refuse leads enabled it is refused. On a channel in the pingtree. The lead enters the offer as normal, but this one channel is skipped. Every other channel still gets its chance. See Pingtree Distribution. Use the offer level for what you do not want at all, and the channel level for what one advertiser will not take. A lead outside your target country belongs on the offer. A lead below one advertiser’s minimum income belongs on their channel. Available Filters Offer if lead is not from an Affiliate partner Offer if lead is from an Affiliate partner Offer if a field value meets a condition Any field from the form can be compared using operators: equals, starts with, ends with, contains, does not equal, greater than, or less than a specific value. Offer if the ratio between values meets a condition Calculates the percentage ratio between two numeric values from the form. Offer based on history Do not use the offer if the lead has already been: sent to this offer rejected by this offer accepted by this offer rejected for a specific reason, which requires selecting both the period and the reason Offer if an external server request returns 200 The request runs while the customer is waiting, so keep the timeout short. A service that takes three seconds to answer costs three seconds on every lead, whatever it replies. Offer if the lead creation time is not within a restricted period Restrict by specific days of the week, for example Sunday, or by time ranges. Limit the number of sold clicks or leads Set a maximum number per period. This is how capping is configured. See Lead and Click Capping. Filter before you ping Every ping costs time the customer spends on a loading screen. A filter that removes a channel which would have rejected the lead anyway saves that time and saves the request. So the rule of thumb is to filter on anything you already know, such as country, product or the partner, and ping only for what you cannot know without asking. #### Offer description Offers can be described in detail to help affiliates better understand the product and how to promote it. You can use a free-text description or two structured tables to present key information more clearly: Key Information – use this section to highlight essential facts about the product, service, or target audience. For example, what the product does, who it is for, pricing specifics, or unique selling points. Rules – clearly define what affiliates are allowed to do and what is prohibited. This helps avoid misunderstandings and ensures that all promotions stay compliant with your brand requirements. You can specify rules around traffic sources, messaging, creatives, and more. Providing clear and complete offer descriptions helps affiliates make better decisions, improves the quality of traffic and leads, and saves time on support and clarification. #### Offer organization You can categorize and customize your offers by adding the following: Logo – displayed in the offer list and available for affiliates to download. System name – shown in the offer list and throughout the system. Display name (optional) – shown on the thank-you page instead of the system name, useful if the system name is not suitable for consumers. Country – assigns the offer to one specific country, or makes it available globally. Used for organizing the offer list. Category – assigns the offer to a single category for easier organization. Tags – allows you to assign multiple tags to an offer for more flexible filtering and grouping. Categories and tags are both managed in Workspace Settings, so the same list is available to every offer. The difference is only in how they are used: one category per offer, any number of tags. #### One Account, Multiple Workspaces PalDock is an ecosystem, not a single affiliate program. Everybody in it, partners, advertisers, and networks, has one PalDock account, and that account connects to as many workspaces as they work with. When somebody registers, the account is created first and immediately connected to the workspace they registered through. Joining a second workspace later does not create a second account. What belongs to the account This data follows the person everywhere and is changed only by them: Email, nickname, and password Billing details Global fields, the shared profile data every workspace can read A change made once propagates to every workspace that person belongs to. What belongs to the workspace This data is yours and nobody outside your workspace sees it: Custom fields you defined in your user structure Country, language, category, and tags you assigned Commission group and the admin who manages the account Offer access and permissions Results, transactions, and balances See Local, Global and Custom fields. What this makes easy One registration. From there a partner can browse the catalogue of offers to promote, and an advertiser can find partners to promote theirs. Joining you is close to one click. Everything global is already filled in. The partner only completes the custom fields you ask for, which is a good reason to ask for few. Data stays current. A partner who changes their company address changes it once, not once per program. What it costs you You cannot change a partner’s basic data. Nickname, email, and password belong to the account, and no workspace permission overrides that. The same goes for billing information. Only the account owner can change it, which matters when an invoice comes back with the wrong details. The fix is with them, not with you. This applies to your own team as well. Admins have PalDock accounts too, so their name and email are theirs, not yours to edit. See Admins. Moving between workspaces Pick the workspace you are working in from the top left corner. Everything on screen, data, reports, offers, and partners, switches with it. Partners manage which workspaces they belong to under the user icon in the top right. Whether new registrations are active straight away and whether your program is listed publicly in the catalogue are workspace settings. See Settings. #### Origin Deduplication Origins are clicks and leads, the first record of a visitor. PalDock counts one visitor once, so repeated clicks and repeated submissions do not inflate your numbers. This is not the same as deduplication based on the advertiser’s ID, which stops an advertiser reporting the same order twice. That happens later, on the conversion. Origin deduplication happens at the start, and it needs no external ID. Nothing is deleted. Duplicates are stored and marked, so you can always see what arrived and what was counted. Click deduplication Each click is compared against the previous ones. It is marked as a duplicate when all of these match: Same IP address Same user agent Same offer Same affiliate Within 1 hour of the original click Together these form the visitor’s fingerprint. The window is fixed at one hour and cannot be changed. The visitor is still redirected as normal. The click simply does not count as a new one. A unique affiliate click ID does not change this. A click carrying its own cid is still a duplicate if the fingerprint matches. A new ID does not make a new visitor. Lead deduplication Leads work differently, because the same person can legitimately send several leads. PalDock separates two questions: was this lead sent twice by mistake, and have we seen this person before. Duplicate leads A lead is treated as a duplicate when all of these match: Same offer Same affiliate Same form data, all filled fields identical Within the duplicate window, 5 minutes by default A duplicate lead is stored with the state Failed and the reason Duplicate. It is not distributed, not paid on, and not counted in your lead totals. Two things worth knowing: The window runs from a successful lead only. If a lead fails and the affiliate corrects it and resends, the corrected one goes through. Only accepted leads block a repeat. Any change to the data makes it a new lead. This check looks at the whole form, so a single corrected digit means it is no longer the same lead. The window is set in Workspace Settings. Raising it above a few minutes rarely helps. If you want to refuse people you accepted last month, that is lead uniqueness, below. Lead uniqueness Uniqueness answers whether this person has appeared in this product before, over days or months rather than minutes. The identifier is a field or a combination of fields you choose, because what identifies a person differs by product. Email and phone by default, a national ID number for loans, a licence plate for car insurance, address and email for utilities. It is set on the structure, since that is where the fields live, and the behaviour is set on the offer or product. A workspace default applies where nothing more specific is set. The affiliate is not part of the match. The question is whether you have this person, not whether that partner brought them before. The window is configurable, 90 days by default, or lifetime. PalDock records two states for each lead: Seen: this person already appeared in the product, in any state. Sent: this person was already delivered to an advertiser. Uniqueness on its own changes nothing. It marks the lead and makes it available to filters, where you decide whether to refuse repeat leads, and to reports. The identifier is stored as a hash, never as the raw value, so anonymising a lead does not break uniqueness. Related leads One person often produces several leads in a short time, for example when an affiliate queries several offers in sequence, or sends the same person to a different product. These are not duplicates and they are all processed normally. They are linked to the first one, and the lead log has a filter to show only the first lead of each group, so a person who generated twenty rows can be read as one. What your reports show Three metrics, three meanings: Gross clicks and gross leads: everything that arrived, duplicates included. Clicks and leads: what was counted, after duplicates. Unique leads: how many of those were the first from that person in the product. Your own numbers may be higher than ours. Two events on your side can resolve to one here. Nothing is lost, the same person is counted once, which is the point. When it gets in the way Testing. Repeated test clicks from one machine collapse into one, and repeated test leads with identical data are refused. Change the network or the browser, vary the form data, or wait out the window. Shared networks. Visitors behind one office or mobile gateway share an IP, but the user agent usually differs, so genuine visitors stay separate. Legitimate repeat customers. Someone who really does apply twice in five minutes is refused. That is the trade-off of a short window, and it is why the window is short. #### Parameters Almost every field in the Connection Creator asks you for a value. You can type it, but usually you pick it, and the picker shows you everything the scenario has available at that point. Form fields The fields of the structure the lead came from, such as first_name or email. What appears here depends on the offer, so two integrations rarely show the same list. Keys The tokens, endpoints and credentials this integration uses. Store anything you would otherwise repeat, such as the base URL or an API key, and change it in one place. See more here. System parameters Values PalDock fills in itself. Always available, never something you set. The full list is below. Previous steps Everything the earlier nodes produced. Each node appears by name, and under it whatever it returned. What that is depends on the node, so this part of the picker looks different in every scenario and changes as you build. An HTTP node gives you the most: the status code, the parsed response body, the headers, and what was actually sent. Other nodes give you what they produce. Only nodes that ran before this one are here, because data travels forward and never back. Reject reasons The standard reasons for turning a lead down. Always available, the same list in every scenario, and unaffected by the offer or by what the earlier nodes did. Pick from here rather than typing, so the spelling is identical everywhere. Reports group reject reasons by name, and a reason typed by hand in one integration will not group with the same reason picked in another. The list is not exhaustive, it is the shared vocabulary. You can write your own value into {reason}, and anything specific to one lead belongs in {reason_detail} instead. See Reject reason for what each reason means and when it applies. How a value is written Picked values appear as a tag in the field. Underneath, they are stored in braces, as {email} or {external_id}. Form fields carry a prefix when they are inserted, so the field you picked as email is stored as {data_email}. That is why a value copied from one integration into another may look different from what the picker showed you. You can type instead of picking, and mix the two in one field: Bearer {token} {first_name} {last_name} Every field with a picker also has a copy button, which is quicker when you need the same value in several places. The system parameters Conversion origin_id : the PalDock ID of the click or the lead. This is the identifier you use to attribute anything back to the affiliate send_id : the PalDock ID of one delivery of a lead to one channel. Use it when you need the conversion tied to a specific channel in a pingtree conversion_id : the PalDock ID of the sale or the prospect. One origin can have several external_id : the advertiser’s own ID for the order affcid : the affiliate’s own ID for the conversion action : whether the conversion is being created or updated type : the conversion type result : the transaction result, such as pending, approved or rejected ip_address : the IP address of the end user For what each identifier addresses and which one to send when, see Conversion IDs explained. Commission value : the order value, used when the commission is a percentage of it commission : the value the advertiser sent in their commission parameter adv_commission : the final commission from the advertiser aff_commission : the final commission for the affiliate commission_profit : the difference between the two commission_id : which commission applies, when several exist for the same type currency : the currency of the offer price : the price the advertiser bid, used in auction distribution Offer offer_id : the ID of the offer offer_name : its name country : its country Advertiser advertiser_id : the ID of the advertiser advertiser_name : their nickname Affiliate owner_id : the ID of the affiliate owner_name : their nickname Integration integration_name : the name of the integration channel_name : the channel name from the pingtree channel_visible_name : the name the customer sees postback_id : the postback the flow belongs to redirect_url : where the customer goes next Time created_date : when the conversion was created, written out timestamp : the same moment as a Unix timestamp timestamp_sign : the timestamp used when signing a request Advertiser custom advs1 through advs10. Ten free slots for whatever a particular advertiser needs. Nothing is predefined, so decide what each one means and keep it consistent. Affiliate custom affs1 through affs10. The same, for values belonging to the affiliate. Execution step_run_id : the ID of this run of this node. Advertisers often want it as a request ID, so a retry can be told apart from a new request random_uuid : a fresh random identifier, generated for each request Security digest : the digest of the request body signature : the signature of the request Both are produced by the Signature setting on the HTTP node, and you place them in the headers yourself. Cookies custom_cookie_ga and custom_cookie_ga_container_id : Google identifiers custom_cookie_gcl_aw : the Google Ads click identifier custom_cookie_fbp and custom_cookie_fbc : Facebook identifiers Use these when forwarding conversions into advertising platforms, which need their own identifier to match the conversion to the click. Where each one can be used This page is about what you can pick while building a scenario. Which parameters may be sent through a pixel, a postback, the Tracking API or an affiliate postback is a different question. See Tracking parameters. #### Performance reports The performance reports answer the everyday questions: what did I pay, what did I earn, and who or what produced it. They are four views of the same data, and what separates them is what a single row represents. The four reports Performance: one row per time period. This is the report you open to see how the workspace is doing over time. It can be filtered by advertiser. Affiliate: one row per affiliate. Filtered by offer. Advertiser: one row per advertiser. Filtered by affiliate and offer. Offer: one row per offer. Filtered by affiliate and advertiser. The built in filters are the ones that make sense for that grouping. Everything else, from tags to countries to transaction types, is available through the normal filters. Drilling down Click an entity name in the first column and the report narrows to that entity and switches to a view by date. From an affiliate row you get that one affiliate’s performance day by day. This is the fastest way to answer why a total changed. The entity report tells you who moved, the drill down tells you when. Secondary grouping Each report has one primary dimension, the thing a row stands for. Secondary grouping adds a second one inside it. Pick it with the layer icon in the table header. The column header gains the name of the second dimension, as Affiliate / Offer. Each row gets an arrow that expands it into the second dimension. The dimension you group by is removed from the columns, since it is now the row key. An affiliate report grouped by offer gives you every affiliate, expandable into the offers each of them ran, without leaving the report. What the columns show Every report carries both totals and averages: Totals: clicks, leads, transactions, costs, revenues, profit. Per lead and per click: CR, CPL, EPL, PPL, CPC, EPC, PPC. Per transaction: ACV and APV. Which ones are on screen is up to you. See Advanced columns for the full set, and Columns explained for how each is calculated. Reading the numbers correctly Two settings change what these reports say, and both are worth checking before you draw a conclusion from them. The reporting time basis decides which day a transaction lands on. The result type filter decides whether pending and rejected transactions are counted at all. A report that looks weak on fresh traffic is usually neither of those things being wrong. It is approved only, on origin time, with most transactions still pending. The chart The chart above the table plots the active Highlights. In the entity reports you can plot individual rows instead and compare up to ten of them against each other. See Show rows in chart. #### Pingtree Distribution A Pingtree is a feature that allows you to send a lead to multiple companies at once. Instead of linking one offer to one advertiser, a pingtree lets you group several offers together and decide how they will be distributed. It works on the Ping and Post basis, where you offer the lead (ping) and if the advertiser wants to buy it, then you send it (post). Think of it as a smart router for your traffic. It decides who gets the customer based on the rules you set. Settings Each line (channel) in a pingtree can have its own settings: Channel Name – the internal name, used in reporting and debugging. We recommend short, structured names such as channelname_model, for example paldock_new_cpl, so you can filter later by prefix, suffix or middle. Visible Name – the name the customer reads on the Choice Page and the Final Page, and the one returned as channel_name in the External Final Page response. Use the company’s real name here, not the internal one. Offer – which offer the channel belongs to. Integration – which integration sends the lead to the advertiser. This is what actually does the ping and the post. Distribution Type – which of the four distribution logics applies to the channel. Redirect Type – whether the customer goes straight to the advertiser’s site, stays on a final page, or is only shown there. Commission – the current commission settings for the channel, with the option to create a new one. Filter – conditions that define whether the lead is offered to this channel at all. See Filters. Channel Status – active or inactive. Position – where the channel sits in the pingtree. Drag it to reorder. Position decides evaluation order and, in Choice, the order the customer sees. Distribution Types Pingtree works in four types of distribution logic. These can also be combined: Exclusive – customers are sent to one company at a time, in pingtree order. If the company accepts, the sale ends. If not, the customer continues down the line until someone accepts. Non-Exclusive – the lead is offered to all companies at the same time, regardless of order in the pingtree. Multiple companies can accept it simultaneously. Auction – the customer is offered to all companies (ping), and each returns a price (a positive number with a dot as the decimal separator; convert it in Modify if the advertiser sends it differently). The customer is sold (post) to the highest bid. Choice – the customer is offered to all companies (ping). The customer sees all successful ping channels on the Choice Page, ordered by their position in the pingtree, and selects which ones they want to apply to (post). Then they see successful post channels on the Final Page where they can complete their application. If a channel has no ping method, it is shown on the Choice Page automatically. Exclusive follows the order you set, so put the channel you expect to earn most at the top. That is usually not the highest raw commission but the highest expected value, which is the commission multiplied by how often that advertiser actually accepts. Redirect Types The Redirect Type defines what happens to the customer after the channel succeeds: Priority – immediately redirects to the first successful channel in the pingtree. Since it always takes the first success, order the channels carefully. FinalPage – the channel is displayed on the final page alongside other offers, each with a button leading to the advertiser. Visible Only – the channel is displayed on the final page but with a disabled button, so the customer cannot be redirected to it. Hidden – the channel is not shown on the final page at all. A single channel set to Priority overrides everything else. If it succeeds, the Final Page is never displayed and nothing else is shown, however many other channels also succeeded. Combination of Distribution types All four logics can be combined within a single pingtree. When they overlap, the system follows these rules: Exclusive, Choice and Auction channels are evaluated as grouped blocks, based on their position in the pingtree. Once the system moves to a different type, the previous block is finished. For example, all Auction channels in one block are resolved first, and if no sale occurs, the pingtree continues with the next type. Non-Exclusive channels always run simultaneously, either alongside the first Exclusive channel or alongside the next block. Examples: Non-Exclusive before Exclusive – runs in parallel with the first Exclusive. Redirect goes to the first Priority channel or to the Final Page. Non-Exclusive before Choice or Auction – runs in parallel with the whole Choice or Auction block. Redirect again goes to the first Priority channel or to the Final Page. Non-Exclusive after Exclusive, Choice or Auction – only executed if all previous channels in those blocks were unsuccessful. What happens to each channel Every channel in the pingtree ends up with one of four outcomes, and you see them in the Pingtree report: ok – the advertiser accepted the lead. fail – the advertiser did not accept it, or the integration could not complete. processing – the channel is being worked on right now. waiting – the channel has paused and expects something to arrive, typically a webhook from the advertiser. A pingtree that leaves channels in waiting for a long time is worth looking at. The customer is not waiting with them, so a late answer arrives after they have gone. Where the Customer is actually Redirected When a lead is created, either through an iframe form or through the API, PalDock immediately generates a process URL for that lead: https://portal.paldock.com/{tenant}/processes/{process_id} This always exists, whatever the pingtree does. For iframe forms the customer goes there immediately. For API leads it comes back as url in the response and the affiliate must send the customer there. See API integration. The process URL is always opened as a full page on your own domain, never inside the affiliate’s iframe. That is deliberate: a full page means first-party cookies and a clean full-screen experience, while an iframe would depend on third-party cookies and be visually limited. You can replace the PalDock domain with a custom domain of your own. The customer first sees a loader screen, then a sequence of internal screens such as verification, thank-you page and final page, depending on how the lead is processed. Admins design these in Design and arrange them into funnels in Funnel. Where each channel sends the customer That is a different URL, one per channel, and it comes from the advertiser rather than from PalDock. In the channel’s integration, the HTTP node’s response mapping stores the advertiser’s destination in redirect_url. That is the address behind the button on the Final Page, and the target of a Priority redirect. A channel that accepts the lead but returns no redirect_url has nowhere to send the customer. Visualisation Example, a Final Page with four successful channels: Company4, Redirect Hidden, so it is not visible. Company3, Redirect Visible Only. Company1 and Company2, Redirect FinalPage. If any of these channels had Priority, the Final Page would not be displayed at all and the customer would be redirected immediately. When a channel is deleted or moved Channels are soft deleted, which means a deleted channel is still visible and still works on Final Pages created before it was removed. This is deliberate. The channel was active at the moment the lead was created, so it was part of that lead’s flow. If capping deactivates a channel, leads that already went through it keep it. A deleted channel is still visible on older Final Pages. Its link still works for historical leads. Deletion or deactivation affects future leads only. There is no full delete, so a channel never disappears from Final Pages that already exist. The same applies to moving a channel. It can be dragged to the end of the pingtree, or from a Non-Exclusive block into a Choice block, and older Final Pages keep the original arrangement, because that was the valid configuration when those leads were created. #### Pingtree reports The pingtree report follows a lead through distribution: how many arrived, how many were offered, who checked them, who verified them, who bought them, and what that was worth. It is the report you open when leads are arriving but not selling. Two levels: Pingtree report: one row per offer. Specific pingtree report: one row per channel inside one offer. Click an offer name to drill into it. Both end with a SUM row totalling every column. Channels appear under the names you gave them in the pingtree. See Pingtree Distribution. Grouping The first column is the Offer. Below that you can regroup the report: By channel By affiliate By advertiser By product By date Secondary grouping works from the same set, so you can look at channels broken down by affiliate, or affiliates broken down by date. The dimension you group by moves out of the columns and becomes the row key. See Performance reports for how the grouping controls work. The columns The columns follow the order of the flow, so you can read a row left to right and see where leads dropped out. Volume Total: leads that entered the pingtree Filtered: leads a channel filter kept out before anything was sent Ping Checked: leads offered to the channel Refused check: the channel said no at the ping Error check: the ping failed technically, for example a timeout or a 5xx Verification Verify: leads sent for verification Verified: leads that passed it Refused verify: verification came back negative Error verify: verification failed technically Post Send: leads posted to the channel Accepted: posts the channel accepted Refused send: posts the channel rejected Error send: the post failed technically Outcome Redirected: customers actually sent on to the advertiser Sales: transactions created Rejected: transactions rejected afterwards Money Revenue: what the channel brought in Cost: what you paid your partners for those leads Margin: revenue minus cost EPL: earned per lead CPL: cost per lead PPL: profit per lead Rates Ping rate: successful pings against pings sent Accept rate: accepted against successful pings Sold rate: sold against successful pings The three rates are what make channels comparable. A channel with a high ping rate and a low sold rate is answering everything and buying nothing, which is a different problem from one that never answers at all. Reading it Refused and error are not the same thing. Refused is the channel deciding no. Error is the request not working. A row full of errors is an integration problem, not a lead quality problem. The integration log has the requests behind it. Redirected tells you the lead was alive. A sold lead that never redirected means the customer left before reaching the advertiser. The money columns follow the reporting time basis and the result type filter, the same as everywhere else. The flow columns do not, since pings and posts have only one date. For how each column is calculated, see Columns explained. #### postfix The postfix operation puts a value at the end of the existing one. The original is kept, it just gains something after it. How it works You type the postfix in the operation settings and it is placed at the end of the value. Value: 100 Postfix: USD Result: 100USD Value: 50 Postfix: kg Result: 50kg Value: user Postfix: -01 Result: user-01 Nothing else changes. The operation does not look at what is already there. Mind the space The postfix is joined to the value exactly as you typed it, so if you want 100 USD rather than 100USD, the space goes at the start of the postfix. Whether it belongs there depends on the other side. Check their documentation or an example payload rather than guessing, because both forms look equally reasonable in the editor. It stops being a number Adding text to a number makes the whole thing text. 100 was a number, 100USD is a string. That is fine when the advertiser wants it that way, but it means any calculation has to happen first. Do the math and the rounding, then add the postfix as the last step. It also means you should think twice before doing it at all. Most APIs want the amount and the currency as two separate fields, and an amount arriving as 100USD is a common reason a request is rejected. Add a unit only when their documentation actually asks for it. Use a condition, or it happens every time The operation does not check whether the postfix is already there. Run it twice, or on data that already carries the unit, and you get 100USDUSD. Set the condition so the step only runs when the postfix is missing, for example does not end with it. See Condition Operators and Field value. The same applies when the field can hold values from different sources, where some already carry the unit and some do not. The common uses Currencies and units, where the advertiser expects them joined to the value: 100USD, 50kg, 3.5m. Identifiers and labels, such as -01, -A or -TEST, for values you want to tell apart later. Keep whatever you choose consistent across the workspace. EUR in one integration and € in another turns into a reporting problem long before anyone notices. The other direction To add something at the beginning instead, use prefix. To build a value from several fields at once, write them together in the field, as {amount} {currency}, rather than chaining postfixes. Settings The operation takes one parameter: the text to put at the end. Everything else is the source and the condition. #### Pre-filling fields Forms can be pre-filled by passing parameters in the query string of the page containing the form, in the format data_fieldname=value. The field name is the system name of a field in the offer’s form structure. This reduces friction and improves the user experience by displaying information you already know, such as name, email or phone number. The Pre-filling fields feature must be enabled in the Offer settings. The data_ prefix The prefix is what separates field values from everything else in the URL. affcid is a tracking parameter, data_email is a value going into a field called email. Global fields carry their own prefix instead, so a global email is g_email rather than data_g_email. See Local, Global and Custom fields. Building the URL from a lead you already have If you want to generate a pre-filled URL for each lead, create a hidden form field that combines all the values in this format: data_fieldname1=value1&data_fieldname2=value2&data_fieldname3=value3 Store it without the domain, so you can append it to any destination URL, for example in an email campaign. Remember that values have to be URL-encoded. An address with a space or an email with a plus sign breaks the query string otherwise, and the fields after it are lost. Anyone with the link can read it A pre-filled URL carries personal data in plain sight. It sits in browser history, in server logs on the receiving side, and in the referrer header of anything the page loads. That is usually acceptable for a link you send to that person by email, and not acceptable for a link that could be shared or indexed. Do not pre-fill anything you would not put on a postcard. You might also want to check out the Auto submit feature, which automatically submits the pre-filled form without requiring user action. #### prefix The prefix operation puts a value in front of the existing one. The original is kept, it just gains something at the start. How it works You type the prefix in the operation settings and it is placed at the beginning of the value. Value: 12345 Prefix: ID- Result: ID-12345 Value: 797992279 Prefix: +420 Result: +420797992279 Nothing else changes. The operation does not look at what is already there. Mind the space The prefix is joined to the value exactly as you typed it, so if you need a space between them, type it. Bearer with a trailing space gives Bearer eyJhbGci…, which is what an authorisation header needs. Bearer without one gives BearereyJhbGci…, which the other side rejects without saying why. Trailing spaces are easy to lose when copying from documentation, so this is worth checking when a token that looks right keeps being refused. Use a condition, or it happens every time The operation does not check whether the prefix is already there. Run it on a phone number that already starts with +420 and you get +420+420797992279. That matters whenever the data comes from several sources, or when the same field is filled in by hand. Set the condition so the step only runs when the prefix is missing, for example does not start with the prefix, or is less than a certain length for a phone number. See Condition Operators and Field value. The common uses Authorisation headers. Adding Bearer to a token, or Basic to encoded credentials. This is by far the most frequent one. See HTTP request. Country codes on phone numbers. Your form collects the local number, the advertiser wants it international. Identifiers. Advertisers who expect their own IDs to arrive tagged, such as ID- or a partner code. The other direction To add something at the end instead, use postfix. To build a value from several fields at once, write them together in the field, as {first_name} {last_name}, rather than chaining prefixes. Settings The operation takes one parameter: the text to put in front. Everything else is the source and the condition. #### Process refused leads This feature is connected to the Refuse leads setting. By default, a refused lead stops where it was refused. It gets fail in the State column, nothing further happens to it, and it does not appear in standard reports. You find it in the Leads log. Process refused leads sends it through the rest of the flow anyway. The lead stays refused towards the affiliate, so there is no payout and it does not count in reports, but it can still be distributed and the customer can still be redirected. Why this exists A refused lead is a lead you decided not to buy from the partner. That is not the same as a lead nobody wants. Two examples: Embedded form lead. A lead passes form validation but is rejected by filters, for example as a duplicate. It does not increase the accepted lead count in reports, but you can still redirect the customer, for instance to finish an application they left unfinished. API lead. A lead fails validation and the partner cannot correct the data. It remains rejected, with no payout and no effect on reports, but it can still go into the pingtree and be sold. In both cases the partner sent you something you are not paying for, and it would otherwise be thrown away. The partner usually has nowhere else to send it either. Which refused leads continue This is a separate set of rules from Refuse leads, with its own configuration. It is not a single on or off switch. Each rule is set for iFrame only, API only, or both, and carries the same four options as Refuse leads. Here they say which refused leads should still be processed: Everything – every refused lead continues. Validation – only leads refused by validation continue. Filters – only leads refused by the Offer filters continue. Pingtree – only leads refused because no channel accepted them. The first three are the useful ones, because those leads were stopped before the pingtree and there is still a whole flow left to run. Pingtree is available but has nothing left to do. Such a lead already went through the pingtree and no channel took it, so there is no further step to send it to. See Refuse leads for setting the refusal criteria themselves. Who the rule applies to Each rule carries two partner lists. Both answer the same question, which is who the rule applies to. Included partners – only the partners on this list are affected. Everyone else is left alone. Excluded partners – everyone is affected except the partners on this list. The lists are read in a fixed order: If the include list has anyone on it, only that list counts. The exclude list is ignored completely. If the include list is empty, the exclude list applies to everyone else. If both lists are empty, the rule applies to every partner. This means you cannot use both lists together to build an exception. Putting a partner on the include list and on the exclude list at the same time leaves them affected, because the include list wins and the exclude list is never read. Pick one list per rule: Use the include list when the rule is meant for a few named partners. Use the exclude list when the rule is meant for everyone except a few. You can have several rules on one offer, each with its own lists and its own selection. They are evaluated in order, and a refused lead continues as soon as one rule that applies to the partner says so. What it does not change The lead stays refused. It is not counted as a valid lead in reports. The affiliate is not paid for it. So refused describes what you owe the partner, not what happens to the customer. #### Prospect + Sale vs Pending Sale In lead generation there are two ways to model the same journey, and the one you pick decides how many transactions exist and when your partner gets paid. Two events: a prospect and a sale, each paid separately. One event with two results: a sale that starts pending and is approved or rejected later. You can mix them across the workspace, offer by offer. The question is not which is better, it is whether the two steps are worth paying separately for. Prospect and Sale Two conversions, two transactions, two payouts. Use it when both steps have value to you. Common in finance and insurance, where a completed application is worth paying for whether or not the loan is eventually taken. The prospect creates a transaction under a CPL commission. The sale creates a second one under a CPS commission. Both can carry their own conditions, amounts, and results. The partner sees the first payout soon after sending the lead, which matters when you are competing for their traffic. See Transaction type. Pending Sale and Approved Sale One conversion, one transaction, one payout that changes state. Use it when only the finished sale is worth anything. Common in e commerce, where an order can be cancelled or returned and paying on the order itself would mean clawing money back. The sale arrives and the transaction is created as pending. The advertiser confirms or rejects it later, and the same transaction moves to approved or rejected. Nothing new is created along the way. The transaction and its payout follow the advertiser’s decision. See Auto-set transaction result. Which to choose Two steps that are each worth money: prospect and sale. One outcome that needs checking first: pending and approved sale. The practical difference for your partner is when they see the money and how stable their reports look. Two events pay earlier and produce more rows. One event pays later and moves numbers between days as results are decided, which is worth knowing before they ask why yesterday changed. See Reporting time basis. It does not have to be either Conversion types are not limited to prospect and sale. You can define your own for the steps that matter in your vertical, and pay on them the same way. A pingtree offer might record a verified lead, a signed contract, and a first payment as three separate types. See Conversion type. #### Recurrence type ⚠️ This setting is only available for workspace commissions from advertisers, because partner commissions reflect those values. Recurrence limits how many transactions one commission can create for the same customer journey. It protects you when an advertiser sends the same conversion more than once, whether by mistake or because they cannot deduplicate on their side. The options Once: the commission creates one transaction and then stops. This is the default for new commissions. Limited: you set the maximum yourself. Unlimited: the commission is applied every time a matching conversion arrives. Existing commissions keep the setting they already have, so older ones may still be unlimited. Check them if you see repeated transactions. Allowing more than one transaction ⚠️ When multiple conversions are enabled for a single commission, update postbacks will not work unless an External ID or Conversion ID is provided, as the system cannot determine which conversion should be updated. With Once, there is only ever one conversion to update, so an update postback can find it on its own. With Limited or Unlimited there can be several, and PalDock has no way to tell which one the advertiser means. Agree with the advertiser that every request carries an external ID, unique per order, before you move away from Once. A conversion ID works too, when the advertiser stores the one PalDock returned. Without either, updates are ignored and results stay Pending, even though new conversions keep being created normally. What counts towards the limit PalDock counts the transactions already created by this one commission, and only those that match all of the following: They sit on a conversion that belongs to the same original click or lead, anywhere in that chain. The conversion has the same type, so sales and prospects are counted separately. The conversion has the same advertiser. The conversion has the same external ID. Conversions that arrived without an external ID are counted together as one group. Transactions on invalid or rejected conversions are not counted. When the limit applies The limit is checked on conversions that follow an original click or lead. The original click or lead itself is never limited, because there is nothing before it to repeat. When the limit is reached, the commission is no longer offered for that conversion. If another commission matches, that one is used instead. Nothing is created if none does. What this means in practice The limit is per commission, not per offer. Two commissions on the same offer each keep their own count, so one order can still create one prospect transaction and one sale transaction. Because the external ID is part of the match, an advertiser who sends a different external ID for each order can create several transactions from one click even with Once. That is usually what you want for repeat purchases. An advertiser who sends no external ID at all gets one transaction per commission with Once, because everything falls into the same group. An advertiser who sends no external ID at all gets one transaction per commission with Once, because everything falls into the same group. Raising the limit for such an advertiser is rarely useful, because their updates cannot be matched either. Recurrence or deduplication Both prevent duplicate transactions, but they act at different points. Recurrence limits how many transactions a commission may create. It works even when the advertiser sends no external ID. Deduplication based on the advertiser’s ID refuses the duplicate conversion itself, before any commission runs. Use both. Deduplication keeps your conversion data clean, recurrence is the safety net when the external ID is missing. #### Refuse leads Users with access to a specific Offer can view its details together with allowed propagation options (Link, iFrame, API). For iFrame or API submissions, the Admin can configure whether unwanted leads should be rejected. This can be applied to iFrame only, API only, or to both. How leads can be rejected If rejection is enabled in the Offer settings, under Form or API, a lead may be refused at three points: Validation – the lead must pass the rules on the fields it carries, whether that is a field type, a regex or a validation scenario. See Field validation. Offer Filters – the lead must satisfy the Offer’s filter conditions to be eligible for processing. See Filters. Lead Processing Result – the lead must be accepted by at least one channel in the pingtree. If no channel accepts it, it is refused. You can choose which of these a lead must pass before being approved: Everything – validation, filters, and pingtree processing. Validation – field and external validation only. Filters – the Offer filters only. Pingtree – acceptance by at least one channel only. Who the rule applies to Each rejection rule carries two partner lists. Both answer the same question, which is who the rule applies to. Included partners – only the partners on this list are affected. Everyone else is left alone. Excluded partners – everyone is affected except the partners on this list. The lists are read in a fixed order: If the include list has anyone on it, only that list counts. The exclude list is ignored completely. If the include list is empty, the exclude list applies to everyone else. If both lists are empty, the rule applies to every partner. This means you cannot use both lists together to build an exception. Putting a partner on the include list and on the exclude list at the same time leaves them affected, because the include list wins and the exclude list is never read. Pick one list per rule: Use the include list when the rule is meant for a few named partners. Use the exclude list when the rule is meant for everyone except a few. You can have several rules on one offer, each with its own lists and its own set of checks. They are evaluated in order, and a lead is refused as soon as one rule that applies to the partner rejects it. Rules are also separate for iFrame and API, so a partner can be covered by an API rule and not by an iFrame one. If a partner needs a completely different setup, duplicating the offer for them is usually clearer than stacking rules. Lead Approval and Rejection If lead refusal is disabled, the status is always approved. Every lead is marked approved, even if it would not have met the criteria. If lead refusal is enabled: The status starts as pending until processing is complete. If the lead meets the criteria, the status changes to approved. If it does not, the status changes to rejected. Sample API response: { "process_id": "9e886baa-6804-4dfe-baf9-a065b66d7f87", "status": "pending", "url": "https://portal.paldock.com/tenant/processes/9e886baa-6804-4dfe-baf9-a065b66d7f87" } Choosing what to check The four options are not four levels of strictness, they are four different questions. Validation asks whether the data is usable. Turning it on rejects leads the partner could have fixed, which is fair to tell them about. Filters asks whether you want this lead at all. A duplicate or a lead outside your target group is rejected here even though the data is perfect. Pingtree asks whether anyone bought it. This is the strictest in practice, because it makes the partner’s payment depend on your advertisers, not only on the quality of their traffic. Partners notice the difference. A lead rejected because the phone number was wrong is a conversation about data quality. A lead rejected because every advertiser was capped that afternoon is a conversation about your inventory. Tracking Lead Status Affiliates may want to track the status of each lead, whether it was approved or rejected. PalDock provides several ways to obtain this information. For full details, see API integration. Verification Rejection has to be immediate, because the customer is waiting to be redirected. Verification is not immediate, because it waits for the customer to do something, for example confirm a code or sign a document. The two cannot both be true at once, so verification resolves it this way: The lead is set to approved when it reaches the verification step, and the customer is redirected. It stays approved whatever happens next. A customer who never completes the verification does not turn the lead into rejected, and neither does a channel that later declines it. So approved means the lead passed the checks you set and was handed over. It does not mean it was sold. Whether the customer finished, and whether the advertiser eventually paid, is a separate question answered by the transaction rather than by the lead status. An offer with verification will normally show more approved leads than transactions, and that gap is the verification drop-off, not a fault. Tell partners this before they build their reporting on the lead status. A partner who counts approved leads as sales will be wrong by exactly that gap. #### regex-replace The regex-replace operation rewrites part of a value using a pattern. You say what to find and what to put in its place, and every match is replaced. Use it when you need to change a value rather than extract from it: inserting separators, stripping characters, reshaping an identifier. How it works Two parameters. Pattern is the regular expression that finds what should be replaced. Write it without slashes around it, PalDock adds those. Output is what replaces each match. Reference the pieces the pattern captured: $1, $2 and so on insert the first, second and further capturing groups $0 inserts the whole match Pattern: (\d{6})(\d{4}) Output: $1/$2 Value: 1234123456 Result: 123412/3456 The pattern makes two groups, six digits and four digits, and the output puts them back with a slash between them. Groups are numbered from left to right starting at one. What happens when it does not work A pattern that matches nothing leaves the value exactly as it was. This is the safe case. A pattern that is not valid empties the field. A missing bracket, a stray modifier, and the result is nothing at all. Those two look nothing alike in the data, which is useful: an unchanged value means your pattern was fine but did not apply, an empty one means the pattern itself is broken. Writing the replacement Prefer $1 over \1. Both work, but $1 is the recommended form and reads better. Use ${1} when a digit follows the group number. ${1}1 is group one followed by the digit one, while $11 is read as group eleven. To output a literal dollar sign followed by a number, escape it as \$1. Writing the pattern Write the raw expression with no slashes around it. If the value itself contains a slash, escape it inside the pattern. For flags, put them inline at the start: (?i) for case insensitive, (?m) for multiline, (?s) to let the dot match newlines, (?u) for UTF-8. Watch out for greedy matching. .* takes as much as it can, which is usually more than you meant. Use .*? when you want the shortest match, or describe the content precisely instead of using a wildcard at all. Named groups work in the pattern, as (?P<name>\d{2}), but the replacement still refers to them by number. Test the pattern first Try it in regex101.com before pasting it in. You can see what matches, check the group numbering, and confirm the replacement does what you think. This applies double if you had an AI write the pattern. They produce plausible expressions readily and correct ones less reliably, and here a wrong one either does nothing or empties the field. Extracting rather than rewriting regex-replace keeps the value and changes part of it. To pull a piece out and discard the rest, use first-regex-match. Reference See PHP: preg_replace and Pattern Modifiers. #### Reject reason A reject reason says why a lead was not accepted. It turns a failed lead into information you can act on. Two parameters carry it, and they do different jobs: reason_detail answers what the advertiser actually said. Free text, passed through as it came, never aggregated. reason answers what kind of rejection this was. It is a short, repeated label, and it is what the reports group by. Set both wherever you can. reason makes the rejection countable, reason_detail makes the individual lead readable. Always set one If no reason is defined, the lead falls into Error. Error means something broke, and it should stay that way. A lead the advertiser deliberately turned down is not a broken lead, and mixing the two makes both useless in reporting. So map a reason for every rejection path in your integration. If the advertiser gives you nothing to work with, fall back to a general one such as Unspecified. Any reason is better than none. Use the predefined reasons You can write anything into reason, but pick from the standard list wherever it fits. Shared names are what make reporting comparable across advertisers, and the whole point of the parameter is that the same rejection looks the same everywhere. A custom reason is worth creating only when it will repeat across many leads. Anything that is specific to one lead, or to one oddly worded response, belongs in reason_detail instead. Every new string in reason is a new row in the report, and a report with sixty rows of one lead each answers nothing. Keep the names short Reasons are aggregated in reports by name. Every distinct string becomes its own row. That means Not Eligible is a useful line in a report, while We are not interested in this lead at the moment is a line that will never group with anything and will never tell you anything. Keep reasons to one or two words, in English, and reuse the same wording everywhere. The long version is exactly what reason_detail is for. Standard reasons Pick these from the picker rather than typing them, so the spelling is always identical. See Parameters. Phase says where the reason can realistically come from. Submit is the moment the lead is offered or posted to the advertiser. Postback is later, once the advertiser has worked with the lead. Several reasons appear in both, because an advertiser may find the same thing out immediately or a week later. At submit, when the lead is sent to the advertiser: Cap: the advertiser’s daily or monthly limit is used up Outside Hours: outside the advertiser’s accepted hours Product Mismatch: the data does not fit the product, such as amount, term, type, region or segment Invalid Data: the advertiser refused the payload itself, such as a malformed or implausible value At submit or by postback, since the advertiser may find these out immediately or later: Unspecified: the advertiser rejected the lead and gave no reason. We recommend using it as the default reject reason. Duplicate: the same application or order already exists at the advertiser Existing Customer: already a customer, or in arrears with the advertiser Not Eligible: fails a condition you could not check in advance Fraud: suspected fraud or a false identity Blacklist: the person is on the advertiser’s blocklist Invalid Traffic: bots, cookie stuffing, self-referrals, incentivised traffic Test: a test lead or order, not billed Age: outside the product’s age range Verification Failed: invalid document, unfinished BankID, missing paperwork Poor Credit: bad history, low score, negative record in a credit register Low Income: income below the threshold, or an unacceptable income type Too Much Debt: debt and repayments too high relative to income Insolvency: insolvency is in progress or has been filed Debt Collection: enforcement or debt collection against the person No Bank Account: no bank account, or it cannot be verified Out of Stock: the goods are unavailable and the order cannot be fulfilled Not Available: the service is not available at that location, such as coverage or connection Contract Locked: tied to the current supplier, outside the notice period By postback only, once the advertiser has worked with the lead: Uncontactable: could not be reached, contact details do not work Cancelled by Customer: the person refused the offer or cancelled the order Cancelled by Advertiser: the advertiser cancelled it, technically, manually or commercially Expired: the offer was never opened and it expired Withdrawn: withdrawn after the contract, such as goods returned or contract cancelled Payment Failed: payment declined, card refused, proforma invoice unpaid Not Delivered: not delivered, not collected, the address does not exist Chargeback: payment reversed by the bank, which is a fraud signal rather than a withdrawal Duplicate means two things Duplicate is also a lead status, set by PalDock when the same origin arrives twice. See Origin Deduplication. As a reject reason it means something different: PalDock accepted the lead as new, and the advertiser recognised it as one they already have. The status is about your side, the reason is about theirs. Unspecified, not Not Eligible The reject reason should reflect what the advertiser actually told us. Not Eligible means the advertiser named a condition the lead failed, and it was something you could not have checked in advance. Unspecified means the advertiser refused the lead without giving a reason. A flat refusal such as false, rejected, declined, or an empty error object is Unspecified. Every time. This matters because Unspecified is worth checking from time to time. It is a catch-all bucket, so new advertiser-side errors or changes can show up there. It also gives us something to take back to the advertiser: these leads were refused, but no reason was provided. The same rule applies to any specific reason. Map it only when the advertiser actually provided it, and use reasons from the standard list so they group consistently. Technical errors fill themselves in You do not have to map the advertiser’s error responses by hand. When a run reaches a failed End node with {reason} still empty and the last HTTP response was a 4xx or 5xx, PalDock fills both parameters for you: reason becomes HTTP 500, HTTP 429, and so on, one value per status code reason_detail becomes the status followed by the response body Anything you set yourself wins. The automatic value is a fallback for the paths you did not cover, not something that overwrites a mapped reason. Status codes make good report rows because there are only so many of them, and they group by themselves. A block of HTTP 429 is a rate limit to raise with the advertiser, a block of HTTP 400 is your payload, and both are visibly different from a lead the advertiser actually turned down. Your own reasons If nothing on the list fits, create your own. Two rules: keep it short, and write it exactly the same way every time. A typo makes a second row in the report that looks like a second reason. Reasons typed by hand are not normalised, so partner declined and Partner Declined will be two rows. Predefined reasons are, which is the other argument for using them. Where a reason is set The same two parameters are used in both places, and there is only one set of values. A rejection that arrives by postback should carry the same Poor Credit as one decided at submit. In a scenario The reason is stored in the {reason} parameter, the detail in {reason_detail}. There are two ways to write into them. Modify node. One node handles all your reasons, because you can define several conditions inside it. This is the recommended approach, otherwise you end up with twenty Set nodes and twenty connections just to cover the advertiser’s rejection responses. Example, mapping one advertiser response to a standard reason: Title: Reject reason Field: {reason} Source: parsedBody.status (the field in the advertiser’s response) Operator: Equals Value: This lead does not meet our criteria Modification: Set Output: Not Eligible Add another section inside the same node for each further reason. The detail is usually simpler, because it is a straight copy. One section with no condition, writing parsedBody.status (or whatever the advertiser’s message field is) into {reason_detail}, covers every path at once. That is worth doing even before you have mapped a single reason, since it is what tells you which responses to map next. Set node. Also possible, and it writes into {reason} the same way. But you need a separate Set node for every reason, each reached by its own connection with a condition. Use it only when that reason needs its own branch in the flow anyway. In a postback An advertiser deciding later sends reason and reason_detail as parameters on the postback, alongside the identifier and the result. See Tracking parameters. Incoming values are matched against the standard list case insensitively, ignoring spaces, underscores and hyphens, so payment_failed, PAYMENT FAILED and Payment Failed all store as Payment Failed. Anything not on the list is stored as it arrived, trimmed and otherwise untouched, because there is no way to know which capitalisation was meant. That is the practical reason to hand your advertiser the standard list. Whatever they send from it will land in the right report row regardless of how they write it. What the run reports Every run ends in one of these, and the log tells you which. Three of them are not rejections at all, and knowing them apart is what stops you from hunting a bug that is not there. TIMED OUT: something ran out of time, either the node, the whole run, or the pingtree. See Limits and timeouts. BREAKER: a Breaker stopped a loop that had repeated as often as it was allowed to. DEAD END: the flow reached a node and no connection leading out of it matched, so it simply stopped. Nothing was written and no End node was reached. The reason from a failed End node: the flow finished properly and the value of {reason} is reported. This is the only one that is a real rejection, and it is empty when you did not set a reason. Dead End is the one to watch. It is the most common way an integration reports errors it does not really have, and it happens for a simple reason: most scenarios are built for the path where everything works. The advertiser then answers with something nobody planned for, no condition matches it, and the run stops mid-flow. The fix is not clever conditions, it is coverage. Go through the advertiser’s documentation, find every response they say they can return, and give each one a connection that leads somewhere. Anything you cannot enumerate goes down a catch-all branch, matched with a negative pattern against the responses you do know, ending in a failed End node with Unspecified as the reason and the advertiser’s raw response in reason_detail. That way a lead you did not anticipate still arrives as a rejection you can read, instead of as an error you have to investigate. The reason_detail on those Unspecified rows is your list of responses still to map. Where the reasons show up Lead log, on the Not sold status. The detail lists each channel and why. See Logs. Pingtree reject reason report, aggregating what advertisers said at submit. Postback reject reason report, aggregating what they said afterwards. The two reports are split because the questions are different. Rejections at submit are about whether you are sending the right leads to the right channel. Rejections by postback are about what happened to leads that were already bought, and they hit money that has already been counted. Leads refused on arrival are elsewhere None of this covers a lead PalDock never accepted: a missing required field, a failed validation, a lead outside the offer’s filters. Those never reach an advertiser, so no advertiser ever gave a reason for them. They are in the lead log with their own status, and aggregated in the Affiliate Fails report. That report has its own set of causes, technical rather than commercial, and deliberately does not mix with the reasons on this page. #### Reporting time basis Every number in a report has to sit on a day. PalDock lets you decide which day that is, because a single journey has three dates on it: the click or lead arrived on one day, the transaction was created on another, and the result was decided on a third. Three options: Origin time: the day the click or lead was created. This is the default. Transaction time: the day the transaction was created. Approval time: the day the transaction result was decided. Switch between them with the target icon in the table header. What the choice changes It moves transactional metrics only: transactions, costs, revenues, profit, and everything derived from them. Clicks and leads always stay on the day they arrived. They have no transaction behind them, so there is nothing to move. Over a long enough period the totals are the same in all three modes. What changes is which day each amount lands on. Nothing is ever lost. Whichever basis you look at, the payout sits on the partner balance and is invoiced from there. The report is a view, not the source of the money. Origin time Everything is reported back to the day the click or lead was created. A sale confirmed today lands on the day its lead arrived, which may be three weeks ago. Use it when: You are evaluating campaign performance and comparing traffic sources. You want to know what a given day of traffic was actually worth. You are making optimisation decisions on recent activity. What to expect: Historical days keep changing. Yesterday looks incomplete, because transactions from yesterday’s leads are still arriving and will be added to it later. A day is only final once every conversion from it has been decided, which depends on how long your advertisers take. Transaction time Everything is reported on the day the transaction was created, which is the day the conversion arrived and a commission produced a payout from it. Use it when: You want to see what came in during a period, regardless of when the traffic behind it happened. You are reconciling against an advertiser who reports the same way. You are watching conversions arrive day to day. What to expect: It tells you nothing about when the traffic was generated. A strong day here can come from leads bought months ago. A transaction created as pending stays on its creation day even after it is later approved or rejected. Approval time Everything is reported on the day the transaction result was decided, whether that decision was approve or reject. Use it when: You are calculating payouts and issuing invoices. You are closing a month and need numbers that will not move afterwards. You need to see when decisions were actually made, for example how long an advertiser is sitting on pending transactions. What to expect: Transactions still pending do not appear, because there is no decision to date them by. They show up on the day they get one. A rejection lands on the day it was rejected, not the day the sale was reported. Combine this with the Result Type Filter to separate approved from rejected. Transactions that are approved automatically are decided at the moment they are created, so for those the approval time and the transaction time are the same. See Auto-approve transactions. Which one to use Buying and optimising traffic: origin time. Watching results arrive: transaction time. Paying partners and invoicing advertisers: approval time. Comparing numbers Do not compare two periods across two different bases. The same transaction can appear in September on one basis and in October on another. When your numbers do not match an advertiser or an affiliate, check the basis before checking the data. It is the most common reason two correct reports disagree. The Transactions report carries all three dates per row, so you can always see where a specific transaction falls on each basis. #### Result Type Filter Every transaction carries a result: pending, approved, or rejected. The result type filter decides which of them your reports count. Where it is set Per report, from the filter in the table header. The change applies to the report you are looking at. As a workspace default, in Workspace Settings. Every report and the Dashboard open with that selection. The default is Approved. The filter is multi-select, so you can combine results. Selecting all three shows everything. What it affects Transactional metrics only: transactions, costs, revenues, profit, and everything derived from them, such as EPL, CPL, ROI and margin. Clicks and leads are not affected. They have no result, so they stay the same whatever you select. This is worth remembering when a report looks inconsistent. A day can show a thousand leads and no revenue simply because every transaction behind them is still pending and the filter is set to approved. Which selection to use Approved only: what you will actually pay out and invoice. The safest basis for financial numbers. Approved and pending: the expected result, including everything the advertiser has not decided yet. Useful for forecasting and for judging fresh traffic, where most transactions are still waiting. All three: for auditing. This is how you see how much an advertiser rejects, and how much of your traffic is being paid for. Rejected only: to investigate rejections, usually alongside the Transactions report or the conversion log. How results are set The advertiser decides through tracking, by sending the result with the conversion or by updating it later. Auto-approve transactions and Auto-set transaction result set it on the commission. You can set it by hand in the Transactions report, or through manual import. Affiliate and advertiser transactions are synchronised, so one result applies to both sides. Approving on one side approves the other. Together with the time basis The filter and the reporting time basis answer two different questions, and they are usually used together. On approval time, a rejected transaction sits on the day it was rejected. Filtering to rejected then shows you when decisions were made, not when the traffic came in. On approval time, pending transactions do not appear at all, because they have no decision date yet. Including pending in the filter changes nothing there. #### See first results As soon as you start testing, numbers appear on the Dashboard and in reports. Four columns carry everything else. Clicks: traffic through affiliate links. Leads: forms submitted through an iframe or the API. Transactions: what a commission created from a conversion. Costs and Revenues: what you pay and what you are paid, with Profit as the difference. Every other metric in PalDock is derived from these. EPL, CPC, ROI, and the rest are all ratios of the same four numbers. See Columns explained. Clicks and leads count what was accepted The click and lead columns hold what PalDock processed. Anything refused on arrival, whether it failed validation, was filtered out, or was a duplicate, is not in them. It is not lost either, it is in the logs with the reason. That is why three different lead numbers exist: Gross leads: everything that arrived. Leads: what was accepted and counted. Unique leads: how many were the first from that person in the product. Your own numbers will usually be higher than the ones here, because two events on your side can resolve to one lead. See Origin Deduplication. Why the numbers may look wrong at first Three settings change what a report says, and all three have defaults that surprise people on day one. The result type filter starts on approved only. Transactions your advertiser has not decided yet are not counted, so fresh traffic can show leads and no revenue. The reporting time basis starts on origin time. A sale confirmed today is reported back on the day its lead arrived, so yesterday keeps changing. The date range is whatever the picker says. Test conversions arriving late land outside a narrow range. A report that looks empty is far more often one of these than a broken setup. If you want to see everything, set the result filter to all three and widen the range. Where to go next A number looks wrong: check the three settings above, then Columns explained. Something is missing entirely: the logs. A conversion exists but no payout came out of it: the conversion log, then How PalDock picks a commission. #### Set The Set node stores a value so you can use it later. Most often you take something out of a response and keep it: the advertiser’s ID for the lead, the URL to send the customer to, the price they quoted. The value is written to the database, so it survives the run. It is available to the rest of the flow, and afterwards to tracking and postbacks. How it works Each line has two fields. Key is the variable you are writing into, in braces, for example {external_id}. Value is what goes into it. Use the picker to take something an earlier node produced, or type a fixed value. Key: {external_id} Value: {parsedBody.applicationId} Read it left to right: put applicationId from the response into external_id. The name on the right is whatever the advertiser calls it in their response, so it will be different for every partner. There is no Source setting. Where the value comes from is decided by what you pick, so a field from the response body is picked under the previous step rather than selected as “body” somewhere. One node holds as many lines as you need, so a single Set node after a request usually stores everything you want from it: Key: {external_id} Value: {parsedBody.applicationId} Key: {redirect_url} Value: {parsedBody.offerUrl} Store the external ID {external_id} is the advertiser’s own identifier for the lead, and it is the one value worth storing in almost every integration. Once the lead is delivered, everything that happens to it afterwards happens on the advertiser’s side. When they later report that it was approved, rejected or paid, they refer to it by their own ID, because yours means nothing to them. If you never stored it, that report arrives with nothing to attach it to, and the conversion is never confirmed. The same ID is also what stops the same conversion being counted twice. See Deduplication, Deduplication based on advertiser’s ID and Tracking S2S Postback. Store it even when you cannot think of a use for it today. It costs one line, and there is no way to go back for it later. Other variables worth knowing {redirect_url} is where the customer goes next, when the advertiser returns a link. {price} is what the advertiser bid for the lead. You need it in an auction, where the bids decide who wins. See Pingtree Distribution. {reason} is why a lead was rejected. Worth setting on every rejection path, otherwise the lead lands in Error and tells you nothing. See Reject reason. {commission} is what the affiliate earns. You rarely set this in an integration, because commissions are normally worked out from the commission settings rather than from the advertiser’s answer. Anything else you store is yours to name and use: a token the next request needs, a value you want to pass onwards, a flag you check in a later condition. Reading from a response The picker offers everything the earlier nodes produced. Under a previous step you will find its whole result, not only the body, so you can store the status code, a header, or the raw response just as easily as a parsed field. {parsedBody.…} is the parsed body. Follow the structure with dots, and use a number for a position in a list, as in {parsedBody.offers.0.offerUrl}. {status} is the HTTP status code, which is worth storing when you want to see later what the advertiser actually answered. {body} is the raw response as text, for when it did not parse. {headers} are the response headers. If everything you pick out of {parsedBody} comes back empty, check the parser on the HTTP request node before looking anywhere else. Building a value for the next request Storing a response is the common use, but a Set node is also how you prepare something the next node needs. Joining two parameters before encoding them, for example, is a Set node followed by a Modify Field node: Key: {auth0} Value: {client_id}:{client_secret} A value can mix fixed text and references freely, which is what makes this work. When the value depends on the answer A Set node writes what you give it, every time. It has no conditions of its own, so to store one thing on one answer and something else on another, each case needs its own connection with a condition and its own Set node at the end of it. That is fine for two or three cases. Beyond that the canvas fills up with nodes that all do nearly the same thing. Modify Field is the better tool there, because the conditions sit inside the node. Twenty rejection responses mapped onto your own reasons is one Modify Field node with twenty lines, rather than twenty Set nodes and twenty connections. The rule of thumb: Set node when the value is simply there, Modify Field when you have to work out what it should be. An empty Set node is allowed A Set node with no lines does nothing to the data, and that is sometimes what you want. On a branch where the answer is “we looked and found nothing”, it leaves the field empty and lets the flow carry on to the End node, which keeps that branch visible on the canvas instead of leaving a loose end. Common mistakes The two fields swapped. Key is where the value lands, Value is where it comes from. The wrong way round, and you store the literal text into a variable named after a response field. Missing braces. A reference without braces is just text. Not storing {external_id}. Everything looks fine until the first postback arrives and matches nothing. #### Set Event The Set Event element lets you trigger and record custom events during the flow. This can be used to track specific outcomes or behaviors returned by an integration. Set Event – defines an event name and action. Common usage: when a response meets certain conditions (e.g. “Duplicate”), PalDock can log the event and, as a result, update the corresponding data in reporting Events are stored in the system and can be used for reporting, monitoring, or triggering other actions. Example:If the API returns a “Duplicate” response, you can configure a Set Event to increment a metric for Duplicate leads by +1. #### set value The set operation replaces the value with one you choose. It does not look at what was there before. When the step runs, whatever the field held is discarded and your value takes its place. How it works You type the value in the operation settings. It can be: a fixed word, such as APPROVED a number, such as 0 a value built from other fields, using references in braces, such as {first_name} {last_name} Then the condition decides when it happens. This is the important half. The condition is what makes it useful On its own, set is blunt: it overwrites everything, every time. Paired with a condition, it becomes the way you translate your values into somebody else’s. Field: {income_type} equals full-time → employed equals self-employed → self-employed equals pension → pensioner Each line is a set with its own condition, all inside one Modify Field node. Only the matching line fires, and the rest leave the value alone. That is the standard way to map a list of values, and it is why set is by far the most used operation in PalDock. The other common uses Filling in a required field that is empty. Some advertisers reject a request outright when a field is missing, even one they do not care about. A set with the condition is empty puts a placeholder in. Capping a number. The advertiser lends up to 20 000 and your form allows more. A set with the condition is greater than 20 000 and the value 20000 sends the highest amount they can work with, instead of one they will refuse. Normalising several inputs into one. Three different statuses that all mean the same thing, mapped onto a single value the advertiser understands. The catch With no condition, everything is replaced. Set with the condition Always wipes the field for every lead, which is occasionally what you want and usually not. If you meant to change only some values, the condition is not optional. Set does not search inside the value. It swaps the whole thing. To change part of a value, or to match a pattern rather than an exact value, use regex-replace. One condition can cover several values. Rather than writing three lines for three statuses that all map to the same output, use the Regex match operator with approved|accepted|ok. See Condition Operators and Field value. Settings The operation takes one parameter: the value to set. Everything else is the source and the condition. #### Show rows in chart By default the chart plots metrics, one line per active Highlight, each in its own colour. It can also plot the rows of the table instead, so you can compare individual affiliates, offers, or advertisers against each other over time. Selecting rows Hover over a row and a checkbox appears. Select one or more rows and the Show in chart button appears in the table header. Up to 10 rows can be plotted at once. In entity based reports the first 10 rows are already selected when the report opens. The deselect icon clears them all in one click. What the chart does Once you click Show in chart: The button turns into Cancel display and changes colour. With several rows selected, every Highlight except the main one, Transactions, is switched off. Ten rows across six metrics would be sixty lines, which is why only one metric stays. With a single row selected, the Highlights that were active stay active. The chart simply narrows to that one row. Active Highlights are shown in black, inactive ones in grey. A legend appears under the chart listing the selected rows, each with a colour from the same palette the Highlights use. Selected rows and export Selecting rows also changes what you can export. With rows selected, the Selected option becomes available in Export, so you can take out exactly the rows you are looking at rather than the whole table. Time range and granularity The chart follows the period set in the date picker and the granularity chosen next to it: hours, days, weeks, or months. Changing either redraws the chart without affecting which rows are selected. #### Start Every scenario begins with a Start node. It is the entry point: the flow starts here and runs immediately. The Start node itself does nothing to the data. It marks where the flow begins and what kind of flow it is. The type follows the scenario A Start node belongs to one of the four contexts: Integration, Structure, Tracking or Feed. That decides what data the flow receives and what it is expected to give back. See Where Connection Creator is used. Everything the scenario starts with is available from the Start node onwards: the fields of the structure the lead came from, the system parameters, and whatever arrived in the incoming request. One Start, except in integrations Most scenarios have a single Start node. Integrations can have several, because an integration is really several separate flows sharing one canvas. In an Offer pingtree you choose a pingtree type on the Start node: Ping asks the advertiser whether they want the lead, and at what price. Post submits the lead. If you do not choose one, the Start node is a Post. Each of these is an independent path with its own Start and its own End. Never connect them. Some advertisers add a third step, where the lead has to be confirmed with a code sent to the customer. That verification also gets its own Start node. It runs straight away Once the scenario starts, the Start node runs immediately. There is nothing on it to delay that. If the flow needs to wait before doing anything, put a Wait node right after it. #### Start here This section takes you from an empty workspace to one with working tracking and real numbers in it. Nothing here needs to be finished in one sitting. PalDock ships with defaults for almost everything, so the usual route is to build the whole chain quickly, test it, and fill in the detail afterwards. It works the same whether you are a network, an advertiser running your own program, or an affiliate with a workspace of your own. What differs is which numbers you care about. Understand the ground rules Basic visual cues: the layout, the workspace picker, and why the background is sometimes green. One Account, Multiple Workspaces: what belongs to a person’s PalDock account and what belongs to your workspace. This is the one that explains why you cannot change a partner’s email. Conversion, Commission, Transaction: three words used constantly in PalDock. Read this before the setup pages. Set it up First steps to get started: currency, the first offer, commissions, and tracking. The main setup page. Prospect + Sale vs Pending Sale: whether to pay for one step or two. Decide it per offer, before the commissions are built. Tracking guide: which tracking method to use, which identifier the advertiser must send back, and what to hand them. Check that it works Test the Offers: click your own link, submit your own lead, and watch the transaction move through its results. See first results: which four numbers everything else is built from, and why a report can look empty on day one when nothing is wrong. Keep it tidy Dashboard: the daily view, and where partners are approved and payouts handled. Categorization: countries, categories, and tags. They look cosmetic and they are what you filter and group reports by later, so set them as you go. Where to go next Once traffic is flowing, the rest of the knowledge base covers it in depth: Offers, Commissions, Tracking, and Reports and Logs. When something does not appear where you expect it, the answer is almost always in the logs. They record every click, lead, conversion, and request, with the reason attached. #### Test the Offers Test the offer before real traffic reaches it. The steps differ depending on how the offer is promoted, but all three end the same way, with a transaction moving through its results. Before you start Testing runs into deduplication, which is working correctly and looks like a bug. Repeated clicks from the same machine collapse into one. Change network or browser between attempts, or wait out the window. Repeated leads with identical data are refused. Vary the form data. See Origin Deduplication. Testing an affiliate link Open the offer and click Preview Offer, then the Link tab. Choose the affiliate the link should belong to. The default one is fine. Open the generated link. That creates a click. The click gets an Origin ID, carried in the URL as pcid. You can read it from the URL, unless the advertiser strips it, and you will always find it in the click log. On the advertiser’s site, complete whatever the offer is about, a form or a purchase. That is what creates the record on their side and makes them fire a pixel or a postback back to you. Testing an iframe Open the offer and click Preview Offer, then the iframe tab. Choose the affiliate. The default one is fine. Copy the code, embed it on a page of yours, open it, fill the form in, and submit. That creates a lead. The lead gets its own Origin ID, which you will find in the lead log. After submitting you may see processing and then land on the advertiser’s site to finish the flow. Once the advertiser accepts the lead it appears in their system, and from there the conversion comes back to you the same way as with a link. Testing the API Open the offer and click Preview Offer, then the API tab. Choose the affiliate to get the API token. The default one is fine. Copy the endpoint URL, build the request in Postman or any API client using the documentation shown on the offer, and send it. That creates a lead. Read the response and follow the URL it returns to continue. From there it behaves exactly like the iframe test. See API integration. Testing the results However the conversion arrived, it usually lands as pending, because the advertiser does not know yet whether it will stand. If it matches your commission conditions, a transaction is created with that result. Ask the advertiser to fire the same postback twice more: Once with the result approved Once with the result rejected The transaction should move from pending to approved, then from approved to rejected. That confirms all three results are handled and that updates find the right conversion rather than creating new ones. There is a simpler setup for lead based offers. Configure the commission to create the transaction as soon as the advertiser accepts the lead, and no pending postback is needed at all. See Auto-set transaction result. When nothing appears Work backwards through the logs: No click or lead: the click or lead log. If the row is not there, it never reached PalDock. The lead is there but never reached the advertiser: the integration log, one entry per request. The advertiser says they sent a conversion: the tracking log. If the request is not there it never arrived, and if it is, the result says what happened to it. See Tracking errors and reasons. The conversion is there but no transaction: the conversion log, then the commission. See How PalDock picks a commission. #### to-base64 The to-base64 operation encodes a value into Base64, a way of writing anything as plain ASCII text. You need it when an API asks for it, and almost the only time it asks is for authentication. How it works Value: hello Result: aGVsbG8= Value: 12345 Result: MTIzNDU= Value: {"id":1} Result: eyJpZCI6MX0= An empty value gives an empty result. Basic authentication This is the common use, and it takes three steps because the header carries one encoded string rather than two values. A Set node joins the credentials with a colon between them, for example {client_id}:{client_secret}, into a field of its own. A Modify Field step runs to-base64 on it. The header on the request reads Authorization: Basic {auth}. The prefix is Basic , with a trailing space. Not Bearer , which goes in front of a token that is already usable as it stands and never gets encoded. Mixing the two up is the most frequent reason an authentication header is refused. See prefix and HTTP request. It is not encryption Base64 hides nothing. Anyone who sees the encoded string can decode it in a second, and from-base64 will do it for you. It exists to make arbitrary data safe to put in a text field, not to protect it. Treat an encoded secret exactly as carefully as you would treat the secret itself. When not to use it Only encode when the other side specifically asks for it. Sending Base64 to an API that expected plain text gives you a rejection with an unhelpful message, because to them the value simply looks wrong. Bear in mind it also makes the data about a third larger, which matters if you are ever moving something big. The other direction To decode, use from-base64. Reference See PHP: base64_encode. #### to-bool The to-bool operation turns a value into true or false. Use it when the other side expects a real boolean rather than text, and when you want a clean yes or no to branch on later. It changes the type, not just the look of the value. A JSON request then carries true rather than "true" or 1. What comes out The words true and false are understood as what they say. The string "true" becomes true and the string "false" becomes false. This is a PalDock addition, not standard PHP behaviour, and it exists because those two strings are what forms and APIs actually send. Everything else follows PHP’s own rules, where a handful of values count as false and the rest count as true. These become false: false, already a boolean 0, the integer zero 0.0, the float zero "0", the string containing a zero "", an empty string [], an empty list nothing at all Everything else becomes true, including: any number other than zero, positive or negative any non-empty string, including "0.0" and "no" any list with something in it, even a list containing a zero any object The catch "0" is the only non-empty string that becomes false. Everything else with a character in it is true. That means a field filled in as "no", "off" or "nope" becomes true, which is the opposite of what it says. If your values are words rather than flags, do not use to-bool. Use set value with a condition for each value, so you decide what maps to what. Watch the empty case too. A field nobody filled in becomes false, which reads as an explicit no rather than as a missing answer. When the difference matters, handle the empty case separately with do-not-send. An empty list is false and a list holding a single zero is true, which surprises people the first time. When you need it Consents and checkboxes are the usual reason. A form checkbox arrives as text and the advertiser wants a boolean. It is also worth doing before a condition that branches on the value, so you are comparing a real boolean rather than whatever text happened to arrive. Settings The operation takes no parameter. Set the source and the condition, choose to-bool, and there is nothing else to fill in. Reference Apart from the two words above, the conversion follows PHP’s rules for casting to boolean. See PHP: Converting to boolean. #### to-float The to-float operation turns a value into a decimal number. Use it when the other side expects a number and you are holding text. Form fields arrive as strings, so 1.25 typed into a form is the four characters 1.25, not the number. Some APIs do not care, others reject the request. It changes the type, not just the look of the value. The field stops being a string and becomes a float, so a JSON request carries 1.25 rather than "1.25", without quotation marks. What comes out An integer becomes its decimal equivalent. 42 becomes 42.0. A numeric string becomes the number it represents. "1.25" becomes 1.25. A string that starts with digits is read up to the first character that does not belong to a number. "123abc" becomes 123.0. Nothing warns you that the rest was dropped. A string that does not start with a digit becomes 0.0. That covers "abc123", "N/A" and anything else that is not a number. A boolean becomes 1.0 for true and 0.0 for false. Null becomes 0.0. An empty field turns into a zero. A list or an object cannot be converted and causes an error. The catch Everything that is not a number becomes zero, silently. That matters when the value carries meaning. An income field left empty, or filled in as “none”, reaches the advertiser as 0, which reads as “this person earns nothing” rather than “we do not know”. Some advertisers reject on that, others accept the lead and pay less for it. Watch out for the decimal comma as well. A form filled in as 1,25 is read only up to the comma, so it arrives as 1.0. If your fields can contain commas, clean them up with regex-replace before converting. So decide what an empty or invalid value should be before you convert it. Put a condition on the step so it only runs on values that look like numbers, or handle the empty case separately with set value or do-not-send. Float or integer Use to-float for anything with a decimal part: amounts, rates, percentages. Use to-int for counts and whole numbers, and be aware it cuts the decimals off rather than rounding. If the advertiser works in whole units, to-int is usually what you want. If they expect 1200.00, to-float is. Settings The operation takes no parameter. Set the source and the condition, choose to-float, and there is nothing else to fill in. Reference The conversion follows PHP’s rules for casting to float. See PHP: Type Casting to Float. #### to-int The to-int operation turns a value into a whole number. Use it when the other side expects an integer and you are holding text, or when a value carries decimals that have no business being there. It changes the type, not just the look of the value. A JSON request then carries 42 rather than "42", without quotation marks. What comes out A numeric string becomes the number it represents. "42" becomes 42. A string with decimals loses them. "1.25" becomes 1. A float loses them too. 1.25 becomes 1 and -3.9 becomes -3. The decimals are cut off, not rounded, so 2.9 becomes 2 and never 3. A string that starts with digits is read up to the first character that does not belong to a number. "123abc" becomes 123. A string that does not start with a digit becomes 0. That covers "abc", "N/A" and anything else that is not a number. A boolean becomes 1 for true and 0 for false. Null becomes 0. An empty field turns into a zero. A list or an object cannot be converted and causes an error. The catch Two things bite here, and both are silent. Decimals disappear rather than round. An amount of 1999.90 becomes 1999, and a rate of 0.95 becomes 0. If the value is money and the advertiser works in whole units, that is what you want. If it is a rate or a percentage, to-int destroys it, and to-float is the right operation. Anything that is not a number becomes zero. An income field left empty, or filled in as “none”, reaches the advertiser as 0, which reads as “this person earns nothing” rather than “we do not know”. Some advertisers reject on that, others accept the lead and pay less for it. Watch the decimal comma as well. A form filled in as 1,25 is read only up to the comma, so it arrives as 1. If your fields can contain commas, clean them up with regex-replace first. So decide what an empty or invalid value should be before you convert it. Put a condition on the step so it only runs on values that look like numbers, or handle the empty case separately with set value or do-not-send. Careful with codes A number that is really an identifier should stay a string. Bank codes, product codes and postal codes often start with a zero, and to-int throws it away: 0100 becomes 100. Use to-int for quantities and amounts, not for anything you would never do arithmetic with. Settings The operation takes no parameter. Set the source and the condition, choose to-int, and there is nothing else to fill in. Reference The conversion follows PHP’s rules for casting to integer. See PHP: Converting to integer. #### to-string The to-string operation turns a value into text. Use it when the other side expects a string and you are holding a number or a boolean. Some APIs are strict about it and reject 42 where they wanted "42", especially when the value is an identifier rather than a quantity. It changes the type, not just the look of the value. The field becomes a string, so a JSON request carries "42" with quotation marks rather than 42. What comes out An integer becomes its digits. 42 becomes "42". A float becomes its decimal notation. 1.25 becomes "1.25". A float with nothing after the decimal point loses it, so 42.0 becomes "42", not "42.0". A string is unchanged. true becomes "1". false becomes an empty string, not "false" and not "0". Null becomes an empty string. A list becomes the literal text "Array", which is never what you want. An object can only be converted if it knows how to represent itself as text. Otherwise it causes an error. The catch The boolean is the one that catches people out. true becomes "1" and false becomes nothing at all, so a consent checkbox that was not ticked arrives as an empty field rather than as a “no”. If the advertiser expects the words "true" and "false", or "yes" and "no", do not use to-string. Use set value with a condition for each value, which gives you exactly the two strings they asked for. The same applies to null. An empty value stays empty, so if the field is required on their side you need set value to put something in it, or do-not-send to leave it out altogether. When you actually need it Most values in a scenario are already strings, because that is how form fields arrive. You need to-string mainly after another operation changed the type, for example when to-int or math produced a number and the advertiser wants it quoted. Identifiers are the common case. A number that is really a code, such as a bank code or a product ID, should be a string, otherwise a leading zero disappears and 0100 becomes 100. Settings The operation takes no parameter. Set the source and the condition, choose to-string, and there is nothing else to fill in. Reference The conversion follows PHP’s rules for casting to string. See PHP: Converting to string. #### Tracking and Conversion Logs Two logs, two questions. The tracking log answers “did the request arrive and what did it do”. The conversion log answers “what exists in PalDock now and did it produce a payout”. Start with the tracking log when something is missing, and move to the conversion log once you know the request arrived. Tracking log Records every S2S postback, pixel, and Tracking API request. One row is one flow, and expanding it shows all the individual requests inside. What appears in it: S2S postback: requests received from advertisers. Tracking API: requests PalDock sends to advertisers. Tracking pixel: requests fired by pixel placements. Affiliate postback: outgoing requests that affiliates configured themselves. Affiliates see only their own. What each row tells you: State: whether the request was accepted or refused. Details and reason: the refusal reason, or the processing outcome when it was accepted. The requests inside the flow, when one incoming request triggered several calls. For what each outcome means and what to do about it, see Tracking errors and reasons. Conversion log A consolidated view of every conversion PalDock holds, whatever created it: postback, pixel, Tracking API, manual import, or PalDock itself. What each row tells you: Origin ID, Send ID, Conversion ID, Transaction ID: the whole chain, so you can follow one journey end to end. See Conversion IDs explained. State: whether the conversion is valid, and whether it produced a transaction. Transactions: how many were created and under which commission. One conversion can have several. Why a conversion produced no transaction The conversion matches no commission, usually because of the conversion type. The commission is inactive or outside its active period. The recurrence limit was reached. It was deduplicated on the advertiser’s external ID. The conversion is not valid, for example refused by validation, by a filter, or by the Pingtree. The conversion was created by a commission. Those never trigger commissions again. See Transaction type. Full list of states and what they mean: Tracking errors and reasons. Commission side: How PalDock picks a commission. Conversions you did not create Some rows in the conversion log were created by PalDock, not by a tracking request. A commission whose transaction type differs from the conversion creates the matching conversion and puts the transaction there. The original conversion then carries no transaction, and the new one does. This is expected. Look at the transaction, not at the conversion that triggered it. Which log to use Debugging a request: tracking log. Is it there, was it accepted, what did it say. Confirming a result: conversion log. What was recorded, is it valid, how many transactions came out of it. #### Tracking API The Tracking API is a server-to-server connection that PalDock initiates. It calls the advertiser’s system to ask about a conversion, or sends conversion data out to an affiliate’s system. No browser, no cookies. It is built on the Connection Creator, so it has all the same features, tuned for tracking. See Connection Creator in Tracking. Two audiences use it: Admins, to call the advertiser and retrieve the status of a conversion. Affiliate partners, to forward conversion data into their own systems. The parameters The Tracking API works with the same conversion parameters as pixels and postbacks. Which parameter is available in which direction is listed on Tracking parameters. For the placeholders you insert into the request itself, see Parameters. Conditions Conditions decide whether a Tracking API runs for a given conversion. Each is All by default. Source: All, Link, iFrame, API Conversion type: All, Lead, Send, Prospect, Sale, or a custom type Affiliate: All or specific Advertiser: All or specific Integration: All or specific Channel: All or specific Included offers and Excluded offers: All or specific Result: Not chosen, All, or specific The result condition is the one that changes the most. Set it, and only conversions that produced a transaction are sent. Leave it unset, and every conversion is sent, including those with no payout. Tracking APIs appear in the Tracking API table with the country inherited from the offer. When no offer or several offers are selected, the global country applies and the category stays blank. Triggers The trigger decides when it fires, the conditions decide whether. All: any change to a transaction, created or updated. This is the default. Created: only when a transaction is created. Updated: only when an existing transaction is updated. Which one to pick: Calls to advertisers: usually Created. With All, the call runs on creation, receives a status, updates the transaction, and that update triggers it again. Postbacks to affiliates: usually All, narrowed with conditions. What fires when A click is created: All, Created A sale is created with no commission applied: All, Created A sale is created and a transaction with it: All, Created A lead is created through an iFrame and immediately updated with cookie data by a pixel: All, Created, and then All, Updated for the update. The update is a separate event with its own trigger. A sale is updated with a new value: All, Updated The same sale is updated again with a new result: All, Updated ⚡ If you are not sure, use the All trigger and narrow it with conditions. Only approved transactions: trigger All, condition result is Approved. Only approved transactions that already carry cookie data: trigger Updated, condition result is Approved. The cookie data arrives with the update, so the creation event is too early. Affiliate postbacks A Tracking API created by an affiliate appears in their Affiliate Postback section. One created by an admin does not, even when it is limited to a single affiliate with a condition. Those stay visible to admins only. See Affiliate postback. How many requests an affiliate receives PalDock forwards changes as they happen, so an affiliate normally receives two requests per conversion: one when it is created, one when the result arrives. On creation, the affiliate is notified immediately. The result is usually pending. With auto-approve, the result is Approved right away and the affiliate receives that immediately as well. On updates from the advertiser, such as an approval, a rejection, or a change of amount, PalDock forwards each one. With several commissions, each transaction is sent separately. The affiliate has to aggregate them. Two ways to cut the volume: Filter on result, so pending transactions are not sent at all. Delay the postback, so the affiliate gets one final update once the conversion is settled. Fewer requests, later reporting. Timeouts and retries Each request has a timeout, and you can set how many times it may be retried. Retries are what make it possible to keep asking an advertiser until a pending conversion is decided. Current values are on Limits and timeouts. One advertiser, several tokens When a Pingtree has several channels from the same advertiser and each needs its own authorization token, one Tracking API cannot cover them all. Duplicate it per channel and give each copy the right token. When it does not work Every call is recorded in the tracking log with its response. See Tracking and Conversion Logs and Tracking errors and reasons. #### Tracking by vouchers Tracking by vouchers A voucher is a discount code the customer enters at checkout. Assign a code to an affiliate, and any conversion that uses it is credited to that affiliate. Vouchers are useful where links do not reach: influencers reading a code out loud, printed materials, podcasts, or anywhere the customer arrives without clicking anything. Creating vouchers Vouchers are managed in Tracking, Vouchers. Create them one by one in the table, or import them in bulk. Once created, they can be used in tracking and appear in reports. How they are tracked A voucher is not a separate tracking method. The conversion still arrives through a pixel, a postback, or the Tracking API, and the code travels with it. The advertiser has to send the code the customer used, so agree on that before you hand out any vouchers. Attribution ⚠️ A voucher always wins. When a conversion carries a code that belongs to an affiliate, that affiliate owns the conversion, whatever the click said. Example: A visitor clicks Affiliate A’s link and later buys something. At checkout they enter a voucher that belongs to Affiliate B. The conversion is credited to Affiliate B. This is deliberate. Entering a code is a stronger signal than an old click, because the customer had to get it from somewhere. Worth knowing before you roll them out: A code shared publicly, on a coupon site for example, will pull in conversions that other affiliates brought. Give codes only to partners who are meant to be credited for them. Everything else follows the conversion as usual. The voucher changes who owns it, not which offer, commission, or amount applies. #### Tracking errors and reasons When a tracking request does not do what you expected, PalDock records why in two places. The tracking log records what happened to the request itself. The conversion log records what happened to the conversion the request created. A request can be accepted and the conversion still end up invalid, so always check both. See Tracking and Conversion Logs. What the endpoint returns 200 OK: the request changed something, either the conversion or its transaction. 204 No Content: the request was accepted, but nothing changed. Usually the values sent were the same as the ones already stored. 400 Bad Request: an update request that could not find the conversion to update. 422 Unprocessable Entity: the request failed validation, for example a missing identifier or an unknown conversion type. Treat 204 as a warning rather than a success. It means the advertiser is sending data that has no effect. Request outcomes in the tracking log Ok: the request was processed and something changed. No change: the request was valid but nothing needed updating. Unmatched: PalDock could not find the conversion the request refers to. This is the most common failure. See below. Filtered: the request did not meet the conditions of the postback it was sent to, for example the wrong source, offer, or advertiser. In progress: a scenario is still running. The final outcome is recorded when it finishes. Fail: the request or the scenario ended with an error. The log row carries the error message. Why a request comes back Unmatched The Origin ID was wrong, expired, or belonged to a different workspace. Only the External ID was sent, without the Advertiser ID. On its own the External ID is not unique. The conversion the advertiser refers to was never created, for example because the pixel was blocked. Several conversions match the identifier and PalDock cannot tell which one is meant. See Conversion IDs explained. Conversion statuses Some statuses mean the conversion is fine (status ok), others mean it is invalid (status fail). An invalid conversion is stored and visible, but no commission runs on it, so no transaction is created. Checklist when nothing happens Find the request in the tracking log. If it is not there at all, it never reached PalDock. Check the pixel, the CSP, or the advertiser’s firewall. If the outcome is Filtered, compare the request against the conditions on that postback. If it is Unmatched, check which identifiers the advertiser is sending. If it is Ok or No change, move to the conversion log and read the status. If the conversion is valid but there is still no transaction, the cause is on the commission side. See How PalDock picks a commission. #### Tracking guide Tracking is how conversions get into PalDock. This page is the overview: which method to use, which identifier to send, and what to hand your advertiser. Every section links to the page that covers it properly. The short version. Put the initiation pixel on every page and the conversion pixel on the confirmation page. Add an S2S postback as a cookie free backup. If you send leads through the API or an iframe, most of this gets simpler, because PalDock already knows the lead. The methods Pixel: fires in the browser on the advertiser’s confirmation page. Quick to deploy, depends on cookies, can be blocked. S2S postback: sent server to server by the advertiser. Cookie free and reliable. Tracking API: PalDock calls the advertiser to ask about a conversion, or forwards results out. Manual import: upload conversions yourself when nothing automated is available. Combine at least two. A pixel and a postback together mean a blocked pixel does not cost you the conversion, and PalDock keeps one conversion rather than two. See Deduplication based on advertiser’s ID. Quick start Initiation pixel on every page. It reads the identifier from the URL and stores it for your attribution window. Conversion pixel on the confirmation page only. It creates the conversion and attributes it to the affiliate whose click was stored. S2S postback from the advertiser’s system, as the backup that works when the browser does not. Steps 1 and 2 get you live. Step 3 is what makes attribution hold up. See How to set up pixel tracking. Which identifier to send This is the decision that everything else depends on. A conversion that carries no usable identifier cannot be matched to anything. Origin ID. The ID of the click or lead that started the journey. Your affiliate link carries it as pcid, and the advertiser sends it back as origin_id. One value, two names. External ID with Advertiser ID. The advertiser’s own order ID. On its own it is not unique, in combination with the advertiser it is. This is the pairing to insist on when the offer uses a Pingtree, because several channels share one Origin ID. Conversion ID. The ID of the conversion itself. Used for updating a specific conversion when nothing else addresses it. Ask for the external ID even when the Origin ID is being sent. It costs the advertiser nothing and it is what saves you when the pixel is blocked or the click ID is stripped. See Conversion IDs explained. More than one commission on a type When several commissions exist for the same conversion type, the request has to say which one it means, through commission_id. Without it, the first commission in order for that type is used. See Commission ID. Cookie consent A pixel stores the click ID in the browser, so consent rules apply to it. No consent obligation, or the cookie counts as essential: a pixel only setup is enough to start. Consent required: fire the pixel in the storage mode that matches the answer, and always send the S2S postback as well. Consent is granted in roughly two thirds of sessions, so a pixel only setup silently loses the rest. One trap worth knowing before you build anything: localStorage and sessionStorage are not shared across subdomains. If the homepage is on the main domain and checkout on a subdomain, only a cookie carries the identifier across. See How to set up pixel tracking. Sending leads through iframe or API When the lead comes through PalDock in the first place, tracking is simpler. The lead already exists, so nothing has to be attributed after the fact. What you still need is the advertiser’s external ID stored from their response, so a later postback can find the conversion. See Connection Creator in Integration. What to give your advertiser Everything they need is generated for you in Tracking, Incoming Postback, and on the offer’s Tracking tab. Send them: The URL to call, and when to call it. Which identifier to send back, and that it should be returned exactly as received. The conversion type, so a prospect does not arrive as a sale. The result, and whether they will update it later. Anything else the commission needs, such as a value for percentage payouts. See Tracking parameters. If the advertiser cannot change their parameter names to match yours, they do not have to. A scenario on the postback maps their names onto PalDock’s, using postback_id in the request. See Connection Creator in Tracking. When it does not work The request never arrived: the tracking log is empty for it. Check the pixel, the CSP, or their firewall. The request arrived but did nothing: read the result. See Tracking errors and reasons. The conversion exists but there is no payout: the conversion log, then How PalDock picks a commission. Full detail on every method is in the Tracking section. #### Tracking parameters Every tracking method moves the same set of parameters. What differs is the direction and which parameters are available in it. Pixel and S2S postback bring data into PalDock, usually from the advertiser. Tracking API and affiliate postback send data out of PalDock, to the advertiser or to the affiliate. This page is the reference for what may travel in each direction. For what you can pick while building a scenario in the Connection Creator, see Parameters. The identifiers Four parameters decide whether a tracking request matches anything at all, so read these before the rest: origin_id is the click or the lead. send_id is one delivery of that lead to one channel in a pingtree. One lead can have several. conversion_id is the sale or the prospect. One origin can have several. external_id is the advertiser’s own ID for the order, sent together with advertiser_id. To create a conversion, send the origin_id, or the advertiser_id together with the external_id. Sending both pairs is the safest option. To update one, send the external_id with the advertiser_id, or the conversion_id when you have it. Full detail on which to send and when: Conversion IDs explained. The full list A ✅ means the parameter can be used in that direction, a ❌ means it cannot. The first column is the group the parameter belongs to, so you can sort the table by it. [table id=2 /] Parameters with a prefix Two entries in the table are patterns rather than fixed names: data_XYZ is any field from the form structure, with data_ in front of its system name. A field called email is sent as data_email. See Local, Global and Custom fields. custom_XYZ is anything you send with a custom_ prefix. PalDock stores it whether or not it is defined anywhere, which makes it the place to put values that have no parameter of their own. The custom_cookie_ parameters are separate from these. They carry advertising platform identifiers collected in the visitor’s browser, and the names are fixed. Forward them when you send conversions into Google or Facebook, which need their own identifier to match the conversion to the click. Where to see what was sent Every tracking request is recorded with the parameters it carried. See Tracking and Conversion Logs, and Tracking errors and reasons when a request did not do what you expected. #### Tracking pixel Pixel tracking places a small script on the advertiser’s confirmation page. When the page loads, the pixel fires and sends the conversion to PalDock through the visitor’s browser. It is the easiest method to deploy, but it runs in the browser, so it depends on cookies and can be blocked. Pair it with an S2S postback so you do not lose conversions when the pixel does not fire. The two pixels The initiation pixel goes on every page. It captures the click and remembers it. The conversion pixel goes on the confirmation page only. It reports the conversion. Both are needed. Without the initiation pixel there is nothing to attribute the conversion to. There is also an update pixel, used to add URL and cookie data to a conversion that already exists. Initiation pixel On every page load, this pixel reads the click ID from the URL, stores it for the length of your attribution window, and hands it to the conversion pixel later. That is what credits the conversion to the right affiliate. <script async src="https://palpxl.com/paldock-pixel-1.0.3.js?t=YOUR_TENANT&cookie=1&expiration=43200&pcidParam=pdcid"></script> t: your PalDock account identifier (slug). Required. cookie: where the value is stored. 1 for a cookie (recommended), 2 for localStorage, 0 for sessionStorage. expiration: the attribution window in minutes. 1440 is one day, 43200 is 30 days. Without it, 30 days is used. A conversion that happens after the window closes is not attributed. pcidParam: the name of the URL parameter that carries the click ID. Without it, the pixel looks for pcid. ⚠️ Initiation scripts are versioned. When we release an update, you normally only change the version number in the script, not the implementation. Conversion pixel Placed on the confirmation page only. It creates the conversion and attaches everything needed for attribution and reporting. <script> (function(w,p){p=w.paldock=w.paldock||{};p.q=p.q||[];p.conversion=p.conversion||function(){p.q.push(["conversion"].concat([].slice.call(arguments)))}})(window); // Create a new conversion of type "sale" paldock.conversion({ action: 'create', type: 'sale', advertiser_id: 'advertiser_id', external_id: 'external_id', result: 'approved', value: 100.55, commission: 100.55, commission_id: 'commission_id', affs1: 'affs1', advs10: 'advs10', pcidCookie: 'custom_name', pcidCookieFallback: true, queryParam: { key1: 'utm_content', key2: 'utm_medium', key3: 'utm_source' }, cookieParam: { key1: '_ga', key2: 'fbp', key3: 'fbc' } }); </script> Required: type, advertiser_id, and external_id. The most common optional ones: result: approved or rejected. Without it, the transaction is created as pending. value: the order value, used by percentage commissions. commission: the payout amount, when the advertiser sends it directly. commission_id: which commission applies, when the type has more than one. The full list is on Tracking parameters. Who the pixel belongs to The same conversion type has two pixel versions, and you pick the one that matches who places it. Advertisers report conversions, so they can create and update. Requires the advertiser ID and the external ID. Affiliate partners enrich their own conversions with URL and cookie data, so they can only update. Requires the affiliate ID. Both are in Workspace Settings, Tracking, Conversion types and pixels. Pick the conversion type, then choose the advertiser or affiliate view. Custom types are added in the same place, and each of them gets its own pixel. Matching the conversion The pixel needs to say which click or lead the conversion belongs to. Origin ID, taken from the cookie by the initiation pixel, or passed explicitly. Advertiser ID with External ID, when the advertiser has their own order ID. Affiliate links can only use the Origin ID, because the External ID does not exist yet at click time. iFrame and API integrations can use either. Sending both is safest. See Conversion IDs explained and Tracking processing. Using your own cookie If the advertiser does not want the PalDock initiation pixel, the conversion pixel can read the click ID from a cookie you control. pcidCookie: 'custom_name' reads the value from your cookie instead of pdc_pcid_[tenant-name]. PalDock’s own cookie handling is then not used, and storing the click ID is up to you. pcidCookieFallback: true falls back to the PalDock cookie when your cookie is empty. The default is false. pcidCookie cannot read HttpOnly cookies. Remove the flag or write a non-HttpOnly mirror cookie. To check: press F12, open the Application tab in Chrome or Edge, or Storage in Firefox, expand Cookies, select the domain, and look at the HttpOnly column. The cookie The initiation pixel stores the value in pdc_pcid_[tenant-name]: {"pcid":"1245","expiration":1779778729419} The expiration timestamp comes from the expiration setting in the initiation pixel. The cookie itself lives longer than that timestamp on purpose. Always check the timestamp before using the value, not whether the cookie still exists. Cookie consent ⚠️ If you use Cookiebot or a similar tool, set it to reload the page after consent, or at least to fire the scripts that were blocked. Otherwise the initiation pixel never runs, no click ID is stored, and you have to handle it yourself. The conversion pixel does not need consent. It stores nothing in the browser, it only reports an event, so it falls outside cookie consent under GDPR. Troubleshooting See How to set up pixel tracking for placement, triggers, ad blockers, and CSP problems. #### Tracking processing This page explains what happens to a tracking request between the moment it arrives and the moment a transaction exists. Every method goes through the same steps: pixel, S2S postback, Tracking API, and manual import. Step 1: the request is checked The request must pass validation. A request without an identifier, or with an unknown conversion type, is refused. If it was sent to a postback that has conditions on source, offer, advertiser, affiliate, or type, it must match them. If it does not, it is logged as Filtered and ignored. The conversion type must be allowed on that channel. Not every type can be created through every method. See Conversion type. Step 2: PalDock finds the conversion Every request has to be tied to something that already exists. PalDock looks in this order: Advertiser ID together with External ID Origin ID If neither matches an existing conversion, the original click or lead is used as the parent When several conversions already exist under one origin, PalDock narrows the search to the child conversions of the type in the request. If exactly one matches, that one is used. If several match, the request is logged as Unmatched and nothing happens, because PalDock cannot guess which conversion was meant. Affiliate links cannot use the External ID, because it does not exist yet at click time. Use the Origin ID. iFrame and API integrations can use either. Sending both is the safest option and works in every case. See Conversion IDs explained. Step 3: create or update The action parameter decides what happens next. action=create records a new conversion. The type parameter is required. action=update changes an existing one, for example to set the result or the value. If action is missing, the request is treated as a create. Two cases worth knowing: An update that finds no conversion returns an error and changes nothing. An update that lands on a click, lead, or send while carrying a different type creates a conversion of that type instead. This is how a sale reported against a click ends up as a sale conversion rather than overwriting the click. Send create=false when you want an update to fail rather than create anything. Step 4: duplicates are filtered out If the advertiser sends an External ID, PalDock checks whether a valid conversion with the same External ID, advertiser, and type already exists. If it does, the new one is stored as a duplicate and no transaction is created. See Deduplication based on advertiser’s ID. If the first request arrived without an External ID and a later one brings it, PalDock saves it onto the conversion. A value that is already stored is never overwritten. Clicks, leads, and sends never carry an External ID. Step 5: commissions run Only now does PalDock look at commissions. A recorded conversion does not mean a payout. The conversion must match a commission’s conditions. The commission must be active, within its period, and within its recurrence limit. See How PalDock picks a commission. Combining tracking methods Most setups run more than one method, because each fails in different circumstances. Pixel: fires immediately on the confirmation page, and is lost when the browser blocks it. S2S postback: arrives when the advertiser processes the order, from seconds to days later. Some send daily batches. Tracking API: PalDock asks the advertiser, so the timing is yours to control. Manual import: the fallback when nothing else is available. The same conversion can therefore arrive up to four times. The External ID is what keeps it as one conversion, so agree on it with every advertiser before going live. What to send Always: an identifier, either the Origin ID or the Advertiser ID with the External ID. When creating: type. When more than one commission exists for that type: Commission ID. When you have it: result, value, and the External ID, every time, even on updates. The full list is on Tracking parameters. #### Tracking S2S Postback An S2S postback is a request the advertiser’s server sends directly to PalDock. No browser, no cookies, nothing to block. It is the most reliable way to receive conversions and the method we recommend to every advertiser, on its own or alongside a pixel. The endpoint https://api.paldock.com/api/tenant-name/postbacks/handle Three ways to identify the conversion: By Origin ID ?origin_id={origin_id}&type={sale}&result={approved}&action={create} By Advertiser ID and External ID ?advertiser_id={advertiser_id}&external_id={your_external_id}&type={sale}&result={approved}&action={create} By both, which we recommend ?origin_id={origin_id}&advertiser_id={advertiser_id}&external_id={your_external_id}&type={sale}&result={approved}&action={create} Affiliate links can only use the Origin ID, because the external ID does not exist yet at click time. iFrame and API integrations can use either. See Conversion IDs explained. The main parameters type: the conversion type. Required when creating. action: create or update. Without it, the request is treated as a create. result: approved, rejected, or pending. Sending it on an update changes the transaction result. value: the order value, used by percentage commissions. commission: the payout amount, when the advertiser calculates it themselves. external_id: the advertiser’s own order ID. Always ask for it, even when the Origin ID is sent. commission_id: which commission applies, when the type has more than one. postback_id: which postback the request belongs to. Required when that postback has a scenario. create=false: refuse to create anything if the update finds no conversion. The full list is on Tracking parameters. Postbacks and conditions A global postback exists by default with every condition set to All, so an advertiser can start sending immediately. Create your own when you need different handling for different partners. Conditions decide whether a request is accepted: Source: All, Link, iFrame, API Conversion type: All, Prospect, Sale, or a custom type Affiliate: All or specific Advertiser: All or specific Offer: All or specific A request that does not match the conditions is logged as Filtered and nothing happens. Postbacks appear in the postback table with the country inherited from the offer. When no offer or several offers are selected, the global country applies and the category stays blank. Scenarios Some advertisers only tell you that something changed, without saying what. A scenario lets the postback call them back and fetch the rest, or transform the incoming data before it is stored. Two common uses: Fetching missing data: the advertiser sends an ID, PalDock calls their API for the status and the value. Mapping parameter names: the advertiser sends their own names and their own status values, and the scenario translates them into PalDock’s. ⚠️ When a postback has a scenario, postback_id becomes mandatory. Without it the request is still received, but the scenario does not run. Ask the advertiser to add it to the URL, for example ?postback_id=value. See Connection Creator in Tracking. Creating and updating Create records a new conversion and needs type. Update changes an existing one, typically to set the result or the value. An update that finds no conversion creates one instead, as long as type is present and create=false is not. An advertiser who reports a sale on a click or a lead does not overwrite it. PalDock creates a sale conversion under it. See Tracking processing. What comes back 200: something changed. 204: accepted, but nothing changed. Usually the values were already stored. 400: an update that found no conversion. 422: the request failed validation. Treat 204 as a warning. See Tracking errors and reasons. #### Transaction type ⚠️ This setting is only available for workspace commissions from advertisers, because partner commissions reflect those values. Transaction type sets what kind of transaction a commission creates. You can choose any conversion type, including custom ones. By default, the system has the following transaction types. [table id=7 /] The default If you leave the setting empty, the transaction gets the type of the conversion that triggered the commission. A sale conversion creates a sale transaction, a prospect conversion creates a prospect transaction. Why you would change it To pay for a different event than the one that arrived, for example paying a prospect commission on an incoming sale. To split payouts inside one offer, with one commission for prospects and another for sales. To group several custom conversion types into one transaction type for reporting. Combine it with the other commission conditions so each commission catches the right conversions. See Prospect + Sale vs Pending Sale for a worked example. When the type differs from the conversion A transaction always belongs to a conversion of the same type. When the transaction type is different from the type of the conversion that triggered the commission, PalDock creates the missing conversion for it. PalDock first looks for an existing conversion of that type under the same original conversion. If it finds one, the transaction is added there. If there is none, PalDock creates a new conversion of that type and puts the transaction under it. The new conversion inherits the data of the conversion it came from, so the affiliate, offer, and IDs stay the same. The new conversion never triggers commissions again, so this cannot loop. One commission creates one transaction on that conversion. If the same commission runs again for the same conversion, no second transaction is added. What you see as a result: Reports count the new conversion under its own type. An extra conversion appears in the conversion log, and the original conversion carries no transaction. The workspace transaction and the partner transaction both sit on this new conversion. #### Transactions report The transactions report is the row level view of the money. One transaction is one row, and both sides of it, what you pay the affiliate and what the advertiser pays you, live in the same table. Click a row to open the drawer, which shows the full detail of that transaction and the conversion behind it. Where transactions come from Transactions are not created here. A commission creates them from a conversion, which is why a conversion with no matching commission produces no row in this report. What you do here: Change a result, individually or in bulk. Export the table. See Export. Correct data in bulk by importing the conversions the transactions hang from. See Import and Manual Tracking and Transaction Import. Results Every transaction carries one of three results: Pending Approved Rejected Workspaces with billing enabled also see Invoiced and Paid, which describe where the amount is in the payout process rather than whether it was accepted. Affiliate and advertiser transactions are synchronised. Approving or rejecting one side applies the same result to the other, so the two can never disagree. See Commissions. Columns Beyond the amounts, the report carries the detail you cannot get from an aggregated report: Origin ID, Send ID, Conversion ID, Transaction ID, the whole chain behind the row. See Conversion IDs explained. Transaction type: prospect, sale, or a custom type Origin type: click or lead, and source type: link, iframe, or API Commission ID, the commission that created the row Value and coupon Product affs1 to affs10 and adv1 to adv10, the custom values the partner sent Device, user agent, and referrer Each row also carries all three dates: when the origin was created, when the transaction was created, and when its result was decided. That is what the reporting time basis switches between, and the report is the place to see all three side by side. See Advanced columns for the full picker and Columns explained for how each is calculated. What partners see Affiliates and advertisers use the same report, restricted to their own rows. Affiliate view Their own transactions only. Costs is labelled Revenue, since from their side it is what they earn. Value, Revenue, and Channel are hidden. Which channel bought a lead is not something a partner is shown, and no filter or grouping will reveal it. Advertiser view Their own transactions only. Revenue is labelled Costs, since from their side it is what they pay. Costs is hidden. #### Translations Each field can be translated into multiple languages to provide a localized user experience. Translations apply to both the Label (Name) and the Placeholder of the field. Language – choose the target language from the dropdown. Name – the translated label that will be shown to the user. Placeholder – the translated helper text displayed inside the input before it is filled. You can add multiple translations for the same field by clicking Add. Each translation can be managed individually, and existing translations can be removed if no longer needed. Additionally, translations can be imported or exported in bulk using the Import and Export buttons. This is especially useful when maintaining large forms or when collaborating with professional translators. The language of the form is controlled in the Form Settings and depends on the chosen form design. Once a language is set for the form, the corresponding translations for each field (Name and Placeholder) will be applied automatically. What a translation does not change The form language only changes the labels and placeholders shown to the user. Everything else stays the same: The system name of the field, which is what integrations map and what the API expects. The values behind Select and Radio options. Only their labels can be translated, so an advertiser receives the same value whichever language the visitor saw. Validation, Modify and AutoComplete, which run identically in every language. That last point is the one that catches people out. A phone regex written for one country’s format does not become a different regex because the form is shown in another language, and an address service that only covers one country still only covers that one. When a translation is not enough If you need a form in a specific language with its own validation rules, its own scenarios, or different fields, create a separate form structure instead of relying only on translations. A rough line to draw: Same fields, same rules, different words is a translation. Different rules, different scenarios, or different fields is a second structure. A missing translation is not an error If a field has no translation for the language the form is set to, the original label and placeholder are shown instead. Nothing breaks and nothing is reported, so a partly translated form looks finished from the admin side and mixed to the visitor. Use the Export button to see which fields are still missing, rather than clicking through the form. #### unix The unix operation turns a date into a Unix timestamp, the number of seconds since 1 January 1970. Use it when an API expects a number rather than a written date, and when you want to compare two dates by size rather than by text. How it works Give it a date and you get a number back. 2024-12-25 → 1735084800 2025-03-01 12:00 → 1740830400 01/01/1970 → 0 The timestamp is always counted in UTC. When it cannot read the date The field keeps its original value. Nothing is logged and no error is raised, so a date the operation could not understand travels on to the advertiser exactly as it arrived. That is worth planning for, because the failure looks like nothing happened. If the advertiser expects a number and receives 25.12.2024, they will reject the lead and the reason will not mention dates at all. Put a condition on the step, or check the value afterwards, rather than assuming the conversion worked. Formats it understands Anything written the international way is safe: 2024-12-25 or 2024-12-25 14:30:00. Formats with slashes are read the American way, so 01/02/2025 is the first of February, not the second of January. If your dates arrive in a local format, reformat them first with format-date rather than hoping they are read correctly. A date written as 25.12.2024 is not understood at all and comes back unchanged. Working with other date operations The three date operations are built to be chained: modify-date shifts a date forwards or backwards format-date writes it a different way unix turns it into a number Shift first, then convert. A step that adds thirty days and a step that turns the result into a timestamp is the usual way to send an expiry date as a number. Settings The operation takes no parameter. Set the source and the condition, choose unix, and there is nothing else to fill in. Reference Dates are read with PHP’s strtotime. See PHP: strtotime for the full list of formats it accepts. #### Update pixel The update pixel adds data to a conversion that already exists. It does not create anything. It is placed either by the advertiser on the conversion page, or by the affiliate on their form page, to collect URL and cookie values that an iFrame or API form cannot pick up on its own. ⚠️ Tracking cannot create Lead conversions. It can only update existing ones. New leads must come from the form or the API. The script <script> (function(w,p){p=w.paldock=w.paldock||{};p.q=p.q||[];p.conversion=p.conversion||function(){p.q.push(["conversion"].concat([].slice.call(arguments)))}})(window); // Update conversion paldock.conversion({ action: 'update', affiliate_id: 'affiliate_id', // only for affiliates advertiser_id: 'advertiser_id', // only for advertisers external_id: 'external_id', // only for advertisers pldk_conversion_id: 'origin_id', // only if it is not in the dataLayer queryParam: { key1: 'utm_content', key2: 'utm_medium', key3: 'utm_source' }, cookieParam: { key1: '_ga', key2: 'fbp', key3: 'fbc' } }); </script> What it collects queryParam: values from the URL, typically utm tags. cookieParam: values from cookies, typically Google and Meta identifiers such as _ga, _fbp, and _fbc. Up to three keys each. Once they are on the conversion, you can forward them anywhere through the Tracking API, for example into Google Ads or Meta. Which conversion gets updated Two ways to point at it: Origin ID = pldk_conversion_id, on its own. Always available, to advertisers and affiliates alike. Advertiser ID with External ID, for advertisers only. If two conversion types happen in the same session, add type so PalDock knows which one you mean. Use lead rather than prospect when you are updating the original lead, not the transaction. See Conversion IDs explained. Where the Origin ID comes from Every conversion has one, and you need it later to update that conversion. Where you get it depends on how the conversion was created. Created by a pixel: the pixel writes the Origin ID into the data layer automatically. Created through the API or a postback: the response contains it. Store it, then push it to the data layer yourself. {"status": "accepted", "origin_id": "1234"} window.dataLayer = window.dataLayer || []; window.dataLayer.push({ event: 'sale', pldk_conversion_id: id // origin ID received from the pixel or the API }); Use the same event name as the conversion type you created. Who has to do what: Affiliates using an iFrame form: nothing. The form handles it. Affiliates using an API form, and all advertisers: store the Origin ID and push it to the data layer, or pass it in the pixel code. When the value is in the data layer, the update pixel picks it up on its own and you can leave origin_id out of the script. Where to place it On the conversion page, alongside the conversion pixel. The update pixel only fires when an Origin ID is available, so placing it on other pages does nothing. See How to set up pixel tracking. #### urldecode The urldecode operation turns a URL-encoded value back into ordinary text. It is the reverse of urlencode. How it works Value: hello+world Result: hello world Value: info%40firma.cz Result: info@firma.cz Value: %2B420797992279 Result: +420797992279 Value: ahoj+sv%C4%9Bte+%26 Result: ahoj světe & Percent codes become the characters they stand for, + becomes a space, and anything that was not encoded is left alone. Decoding something that was not encoded Because unencoded characters pass through untouched, running this on ordinary text mostly does nothing. Mostly. The exception is the plus sign. A value that genuinely contains one, such as a phone number written +420797992279, comes out as 420797992279 with a leading space. The number is now wrong and nothing about it looks unusual. So decode only where you know the value arrived encoded. If a field is sometimes encoded and sometimes not, put a condition on the step, for example only decoding when the value contains a %. When you need it Values arriving in a query string. An incoming postback or webhook that carries a name or an email in the URL will have them encoded. Reading a value back out of a link. A redirect URL from an advertiser often has parameters inside it, and those are encoded. Checking what a value really is when something looks wrong and you suspect it was encoded twice. A value showing %2540 was encoded once too often, and decoding it once gives you %40. Malformed input A percent sign that is not followed by two valid hex digits is left as it is rather than causing an error. That means a half-encoded value decodes partially and quietly, so the result may be neither the original nor an obvious failure. Reference See PHP: urldecode and RFC 3986. #### urlencode The urlencode operation makes a value safe to put in a URL. Characters that would break the URL, or be read as part of its structure, are turned into percent codes. How it works Value: hello world Result: hello+world Value: info@example.com Result: info%40example.com Value: +420797992279 Result: %2B420797992279 Value: ahoj světe & go Result: ahoj+sv%C4%9Bte+%26+go The rules are simple: spaces become +, letters, digits and - _ . ~ stay as they are, and everything else becomes % followed by two hex digits. Spaces become plus, not %20 Both forms are valid in a query string and most systems accept either. Some do not, and a value that arrives with a literal + where a space should be is the usual symptom. If the other side needs %20, this operation is not the one you want, and it will need to be handled differently. Check an example from their documentation before assuming. Where the plus sign bites A phone number written as +420797992279 encodes to %2B420797992279, which is correct. Left unencoded in a URL, that same + is read as a space, and the number arrives as 420797992279. This is the single most common reason a phone number breaks in a query parameter, and it is invisible until you look at what actually arrived. When you need it Only for values going into a URL, meaning a query parameter or a redirect link you are building yourself. You do not need it for values in a JSON body, and encoding them there sends the advertiser percent codes instead of text. You do not usually need it for the query fields on an HTTP request node either, since those are encoded when the request is built. Encoding twice turns %40 into %2540, which nobody wants. So reach for it when you are assembling a URL as a value, not when you are filling in a request. The other direction To decode, use urldecode. Reference See PHP: urlencode and RFC 3986. #### User structure A User Structure defines the fields collected when users register or manage their account in PalDock. Separate structures exist for Affiliate partners and Advertisers. Used in registration forms and user management. Can include global fields (Name, Email) as well as any custom fields. Admins can customize fields to fit their tenant’s needs. It is not attached to anything Unlike a form structure, a user structure is not connected to an offer or an integration. The registration form and the account page use it directly, so a change takes effect the moment you save it, for people who registered long ago as well as for new ones. Some fields belong to the person, not to you Global fields such as first name, last name and email are tied to the user’s account, which spans every workspace they have access to. When the user changes one of these, it changes in every workspace at once. An admin cannot change them on the user’s behalf. That is deliberate. The same person should not be called two different things in two workspaces. If you need a value that behaves differently, make a local field instead, and accept that it will not be linked to the account. See Local, Global and Custom fields. What to collect A registration form is where partners decide whether to bother. Every field you add is a reason to stop. Ask for what you need to pay them and to know who they are. Anything you only need later, such as billing details or a tax number, can be collected when it becomes relevant rather than at sign-up. Validation, Modify and AutoComplete work here exactly as they do in a lead form, so a company number can be checked against a registry during registration. 👉 For details about field types, validation, Modify, and translations, see the other pages in this section. #### Wait The Wait node pauses the flow, then lets it continue. You use it when the other side needs time before it can answer, and when a retry loop should leave a gap between attempts. How long You set the delay in seconds, minutes or hours. The maximum is one year. What the pause actually does This is the part worth understanding, because a Wait behaves differently depending on whether anyone is waiting for the answer. In a background flow, the pause costs nothing. The run is put down and picked up again when the time is up. A Wait of twelve hours before checking a lead’s status is perfectly normal. In a flow that runs while someone waits, such as an integration in a pingtree, a short pause genuinely holds everything up. The customer sits on the loading screen for exactly as long as you set. The dividing line is around fifty seconds. Below that, the flow simply stops and waits, and the customer waits with it. Above that, PalDock releases the flow instead of holding the line open, and picks it up later in the background. That sounds convenient, but it means the answer arrives long after the customer has gone. A long Wait in a pingtree is not a way to give an advertiser more time, it is a way to lose the sale. See Limits and timeouts. Waiting in a loop The usual pattern is: ask, and if the answer is not final yet, wait and ask again. Get status → still pending → Breaker → Wait → back to Get status Always put a Breaker in that loop. Without one the flow keeps going round until it hits a system limit and fails with an error, which tells you nothing useful about the lead. Set the delay and the Breaker limit together, because what matters is the total. Six attempts twenty-four hours apart covers a week. Six attempts a minute apart covers six minutes, which is not long enough for anything a human has to look at. Common mistakes A Wait in a pingtree with no thought for the customer. Every second is a second they are staring at a loading screen. A loop with no Breaker. It runs until it errors out. A delay that is too short for the advertiser. If they take a day to decide, asking again in five minutes just wastes six requests and ends with nothing. #### Webhook A Webhook node pauses the flow and waits for an external system to call you. You need it when an advertiser accepts the lead but cannot say straight away what happened to it. Instead of asking them again and again, you give them a URL and they call it once they know. That is usually faster and always cheaper than polling. Two ways to wait The setting Pingtree waits until webhook finishes decides how the pause works, and the difference matters more than it looks. Switched on, the flow holds the line open. The pingtree stops and waits, the customer sits on the loading screen, and as soon as the call arrives the flow carries on with the data. Because something is genuinely blocked the whole time, the timeout here is capped at about 40 seconds. Use it only when you are confident the advertiser answers within seconds. If they do not, you have held up the sale for nothing. Switched off, the flow is put down instead. Nothing is blocked, the pingtree moves on, and the run is picked up again when the call arrives. The wait can be as long as 48 hours. This is the right choice for anything the advertiser has to think about, and for anything a human on their side is involved in. What happens when nobody calls The two modes behave differently here as well, which is worth knowing before you pick one. Waiting on the line, a timeout is an error. The run stops and the log says the webhook timed out after so many seconds. Released, a timeout is not an error. The flow simply carries on when the time is up, with none of the data it was hoping for. Put a condition on the connection leaving the node to check whether anything actually arrived, otherwise the flow continues as though it had an answer. Webhook ID Each webhook needs its own ID, and it forms part of the URL you hand to the advertiser. Keep a note of it. If you delete the webhook and build it again later, you can reuse the old ID so the advertiser never has to change anything on their side. Endpoint The URL the advertiser calls. Give it to them together with whatever identifier they should send back. How the call finds the right lead An incoming call has to be matched to the exact run that is waiting for it, and PalDock uses the same two methods as everywhere else in tracking. See Tracking processing. By the PalDock conversion ID. This is the identifier PalDock generated for the lead, and it is unique across the system, so on its own it is enough. Send it to the advertiser when you submit the lead and ask them to return it. By the advertiser’s external ID. Their own identifier for the lead, which is unique only in combination with the advertiser ID. This is why you store {external_id} from the response when the lead is submitted. See Set node. If the call matches nothing, the advertiser gets back: {"code":404,"message":"Waiting Webhook not found for provided token and identifiers"} That response means one of three things: the run already timed out and stopped waiting, the identifier they sent is not the one you stored, or they called the wrong webhook. When the advertiser uses different parameter names Advertisers rarely call these identifiers what you call them. One sends lead_id, another sends operationId, and PalDock does not recognise either. You do not have to accept their naming. In your workspace settings, under Custom ID parameter names in integrations, you list the names they use, and PalDock treats those as the identifier. There are three fields, one for the PalDock conversion ID, one for the advertiser ID, and one for the advertiser’s own ID. Each accepts several names separated by commas, so one setting covers all your advertisers. Fill this in before you go live rather than after. Without it every callback comes back as a 404, and there is nothing in that response to suggest the parameter name is what is wrong. Using what arrived Everything from the call is available to the nodes after the Webhook, split into four parts: body, what they posted queries, the query parameters in the URL headers, the request headers cookies, any cookies they sent Branch on it the same way you would on a response. A callback often carries several kinds of event, so read the field that says which one it is and give each its own connection. Anything you do not recognise should have a path too, otherwise the run ends there. The data stays available for 180 days. Retrying A webhook that never arrives is common enough to plan for. The usual pattern gives it a second chance rather than giving up: Webhook → nothing useful → Breaker → Wait → back to Webhook See Breaker and Wait. Starting a scenario with a webhook A Webhook node can also be the first node in a scenario, rather than a pause inside one. Then it is not waiting for anything in particular, it just runs whenever the URL is called. That is how you handle an advertiser who sends updates on their own schedule, without a lead of yours waiting for them. Common mistakes Holding the line open when the advertiser takes minutes. The customer leaves long before the answer arrives. No check that the data actually came. In released mode a timeout looks exactly like a successful call to the nodes that follow. Not storing {external_id}, so their call has nothing to match against. Their parameter names not registered, so every call comes back as a 404. Changing the webhook ID and not telling the advertiser. #### Where Connection Creator is used Connection Creator is not a separate tool. It is the engine behind every place in PalDock that talks to an outside system. A scenario always belongs to one of four contexts, and the context decides what starts it, what data it receives, and whether anyone is waiting for the answer. Integration Sends a lead to an advertiser and processes the answer. Started when a lead reaches an offer, either directly or through a pingtree. The scenario receives the lead data and gives back the result: accepted or rejected, the redirect URL, the advertiser’s own ID for the lead. See more here. This is the most common use, and it is the one the Integration Library is built for. Structure Runs inside the form itself, while the lead is still being created. See more here. Three purposes: Validation checks a value while the form is being filled in and can block the submit. Modification fills a field with a value from an external service. See Modification. Autocomplete suggests values to the visitor while typing. See AutoComplete. All three run while the visitor is waiting, so they must be fast. See Limits and timeouts. Tracking Handles conversion and status data moving in and out of PalDock. Two directions: Incoming postback processes a conversion or status update sent to PalDock. Outgoing postback sends conversion and status data from PalDock to affiliates or other systems, and can also poll an advertiser for a result. Both run in the background. Nothing is waiting for them, so they can take longer and can pause and resume. See more here. Feed Pulls product or offer data from an external source and brings it into PalDock. Runs in the background on its own schedule. Where scenarios live All scenarios are managed in the Tools menu, in the respective section based on the context they belong to. To add one, click Add and choose either a custom integration or a prebuilt one from the Library of Integrations. If you use global fields, most library integrations are ready after a single click. How scenarios are triggered The context decides what starts a scenario: Integration starts when a lead is sent to an offer, either directly or through a pingtree. Structure starts while data is being entered: a lead in a form, a partner during onboarding, or a record during feed ingestion. Incoming postback starts when PalDock receives a call from an external system. Outgoing postback starts when something happens inside PalDock, for example a new conversion or a status change. Feed starts on its own schedule. ### Reviews #### Jan Stejskal As Affiliate Consultants, we’ve often seen clients struggle to start and grow their programs. We help them find the right solution and avoid common pitfalls. PalDock has been a great help, covering both current and future needs, and preventing the need for migrations to a more robust solution later on. #### Jiří Sillik PalDock has made managing leads and partnerships so much easier. We used to juggle different tools for tracking and lead generation, which made things messy. Now, everything’s in one place. We can collect, track, and manage leads and clicks all from the same software. It’s saved us a ton of time and let us focus on growing the business. #### Martin Mazurek Monetizing display or link traffic has its limitations and doesn’t provide enough differentiation. We shifted our focus to delivering more value to our users and gaining a competitive edge. That’s when we started collecting leads and selling them through API to the highest successful bidder. PalDock handled all the technical heavy lifting, allowing us to concentrate on growing the business without getting bogged down by technical challenges. #### Simone Bertolone We manage traffic through affiliate links and lead generation via API, and having both in one platform is a major advantage. With everything in a single dashboard, we gain full control of our affiliate channels and the flexibility to experiment and optimize more effectively. Since PalDock is designed for affiliates as well, integrating the standardized API is straightforward, allowing them to start sending leads within an hour. ### Integrations #### Sell leads to 7finance (CZ) Advertiser 7finance Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -420, "y": 0 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -210, "y": 0 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_insolvency}", "fields": [ { "source": "{data_insolvency}", "operator": "equals", "value": "no", "value2": "", "modification": "replace", "pattern": "", "output": "NO" }, { "source": "{data_insolvency}", "operator": "equals", "value": "yes", "value2": "", "modification": "replace", "pattern": "", "output": "YES" } ] }, { "fieldName": "{data_distraint}", "fields": [ { "source": "{data_distraint}", "operator": "equals", "value": "no", "value2": "", "modification": "replace", "pattern": "", "output": "NO" }, { "source": "{data_distraint}", "operator": "equals", "value": "yes", "value2": "", "modification": "replace", "pattern": "", "output": "YES" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "HOME_OWNER" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE_BENEFIT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": 20, "y": 0 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/partners-v1/basic-lead", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "X-Token", "value": "{token}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "city", "value": "{data_city}" }, { "key": "uuid", "value": "{eid}" }, { "key": "email", "value": "{data_email}" }, { "key": "state", "value": "CZ" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "mobile", "value": "{data_cell_phone}" }, { "key": "period", "value": "{data_period}" }, { "key": "street", "value": "{data_street}" }, { "key": "expenses", "value": "{data_expenses}" }, { "key": "postcode", "value": "{data_zip}" }, { "key": "agreement", "value": "true" }, { "key": "distraint", "value": "NO" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "marketing", "value": "true" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "insolvency", "value": "NO" }, { "key": "home_status", "value": "{data_home_status}" }, { "key": "income_type", "value": "{data_income_type}" }, { "key": "birth_number", "value": "{data_nin}" }, { "key": "house_number", "value": "{data_house_number}" }, { "key": "monthly_income", "value": "{data_monthly_income}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 270, "y": -100 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.id}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 520, "y": -100 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 270, "y": 130 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.reason}", "operator": "equals", "value": "Empty body", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{parsedBody.reason.city.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.city.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.uuid.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.uuid.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.email.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.email.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.state.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.state.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.amount.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.amount.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.mobile.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.mobile.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.period.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.period.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.street.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.street.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.expenses.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.expenses.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.postcode.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.postcode.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.agreement.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.agreement.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.last_name.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.last_name.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.marketing.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.marketing.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.first_name.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.first_name.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.insolvency.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.insolvency.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.home_status.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.home_status.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.income_type.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.income_type.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.birth_number.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.birth_number.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.house_number.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.house_number.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.monthly_income.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.monthly_income.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.distraint.0}", "operator": "equals", "value": "Field missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason.distraint.0}", "operator": "equals", "value": "Field invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.reason}", "operator": "equals", "value": "Current time period blocked", "value2": "", "modification": "replace", "pattern": "", "output": "Outside Hours" }, { "source": "{body}", "operator": "contains", "value": "Lead insolvent", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{body}", "operator": "contains", "value": "Income type not allowed", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{body}", "operator": "regex_match", "value": "(duplicate|Duplicate|duplicity|Duplicity)", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 520, "y": 130 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "regex_match", "output": "^(OK|OK - CPS)$", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "regex_not_match", "output": "^(OK|OK - CPS)$", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Two endpoints with an identical payload: a check that decides, and a sell that records the lead. Both answer HTTP 200 whatever they think, so nothing may branch on the status code. The decision is status, and the vocabulary is small: OK, OK - CPS, or FAIL. Expect the great majority of leads to come back FAIL with the single word Not acceptable, which says nothing beyond no. What will be needed from advertiser Key Purpose endpoint Base API URL. token API token sent in X-Token. Flows Ping, POST /partners-v1/basic-lead-check. Decides. Nothing is recorded. Post, POST /partners-v1/basic-lead. Same payload plus contact details. Returns the advertiser’s id. Calls POST {endpoint}/partners-v1/basic-lead-check POST {endpoint}/partners-v1/basic-lead X-Token: {token} Content-Type: application/json format: application/json Request fields The ping and the post take the same body. Phone and e-mail are optional at the ping and required at the post. Field Required Value uuid at post {send_id} amount yes {g_amount} period yes {g_period} monthly_income yes {g_fin_income} expenses yes {g_fin_expenses} insolvency yes {g_status}, YES or NO distraint yes {g_status}, YES or NO house_guarantee no {g_asset_status}, YES or NO first_name yes {g_name_first} last_name yes {g_name_last} birth_number yes {g_id_national_number}, no slash street yes {g_address_street} house_number yes {g_address_street_number} city yes {g_address_city} postcode yes {g_address_zip} state yes CZ, the only accepted value home_status yes {g_home_type}, see enums income_type yes {g_fin_type}, see enums mobile at post {g_phone}, at most nine characters email at post {g_email} agreement yes true, must be true marketing no {g_consent_marketing} mobile is capped at nine characters, so a number carrying +420 is refused. Send the national part only. insolvency and distraint are knockout questions the form has to ask; there is no sensible default for either, and guessing NO invents an answer the applicant never gave. Enums income_type: EMPLOYED, PART_TIME_EMPLOYMENT, SELF_EMPLOYED, PENSION, MATERNITY_LEAVE, BENEFITS, SAVINGS, STUDENT, UNEMPLOYED, OTHER. home_status: HOME_OWNER, CO_OWNED, TENANT, DORMITORY, HOSTEL, MINISTRY, EMPLOYEE_BENEFIT. Living with parents maps to TENANT. Outcomes Recognised by HTTP Meaning Reject reason Frequency status: OK + id 200 Accepted occasional status: OK - CPS 200 Accepted for CPS only documented only status: FAIL, reason: Not acceptable 200 Refused, no reason given Unspecified common reason.mobile[] ~ nanejvýš 9 znaků 200 Phone too long Invalid Data rare reason.mobile[] ~ Neplatný formát 200 Malformed phone Invalid Data rare reason.email[] ~ není platná 200 Malformed e-mail Invalid Data rare name: Internal Server Error 500 Advertiser-side failure rare reason has two shapes. On a business refusal it is the string Not acceptable. On a validation failure it is an object keyed by field name, each holding a list of messages, so the useful text is at {parsedBody.reason.mobile.0} with the index. Distinguish the two by matching "reason"\s*:\s*\{ against {body}. That works on both shapes because {body} is raw text; a regex against {parsedBody} matches nothing, because a parsed object is not a string. Not acceptable names no condition and is Unspecified, not Not Eligible. It is the bulk of the traffic and the thing to take back to the advertiser. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted: {status} equals 200 {parsedBody.status} regex match ^(OK|OK - CPS)$ Refused, a catch-all scoped to the business field: {status} equals 200 {parsedBody.status} regex not match ^(OK|OK - CPS)$ 500 carries no business result and gets no branch. Stored values Parameter Source {external_id} {parsedBody.id} from the post There is no redirect URL. The applicant continues on your side. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Cash4Car (CZ) Advertiser Cash4Car Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -158, "y": -20.5 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -11, "y": -91.5 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/poptavky/add", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "HASH", "value": "{token}" } ], "body": [ { "key": "car", "value": "{data_own_car}" }, { "key": "stat", "value": "cz" }, { "key": "email", "value": "{data_email}" }, { "key": "jmeno", "value": "{data_first_name}" }, { "key": "phone", "value": "{data_cell_phone}" }, { "key": "prijmeni", "value": "{data_last_name}" }, { "key": "source_hash", "value": "{eid}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "setNode", "position": { "x": 165, "y": -171 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.redirect_url}" }, { "key": "{external_id}", "value": "{parsedBody.id}" } ] } } }, { "id": "1-5", "type": "endNode", "position": { "x": 353, "y": -140.5 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": 118.5, "y": 10 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.error}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.error}", "operator": "contains", "value": "invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.error}", "operator": "contains", "value": "missing", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.error}", "operator": "contains", "value": "duplicity", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.error}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.error}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 290.5, "y": 10 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.message}", "operator": "equals", "output": "success", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.message}", "operator": "regex_not_match", "output": "success", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details The simplest integration in the library. One call, a handful of fields, and a two-key response. What will be needed from advertiser Key Purpose endpoint Base API URL. token Key sent as the HASH query parameter. Flows Post, POST /poptavky/add?HASH={token}. Creates the enquiry. Calls POST {endpoint}/poptavky/add?HASH={token} Content-Type: application/json format: application/json The key travels as the HASH query parameter. There is no auth header. Request fields Field Required Value source_hash yes {send_id} jmeno yes {g_name_first} prijmeni yes {g_name_last} email yes {g_email} phone yes {g_phone} stat yes cz, also accepts sk, pl, es car yes {g_asset_type} source_hash is the advertiser’s deduplication key and the handle for asking about the lead later. Send {send_id} so the value is reproducible. The product only makes sense for someone who owns a vehicle. Where the form asks and the answer is no, filter before the request rather than sending a lead that will be refused the outcome is a Product Mismatch you can name yourself. Enums None. Outcomes Recognised by HTTP Meaning Reject reason Frequency message: success 200 Accepted , common error ~ missing 200 A required field was empty Invalid Data occasional error ~ invalid 200 A field failed validation Invalid Data occasional error ~ duplicity 200 This source_hash was used before Duplicate occasional error is a free-text string naming the problem, for example missing stat (cz,sk,pl,es). Pass it through whole in {reason_detail} and match the reason on a substring. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted: {status} equals 200 {parsedBody.message} equals success Refused, scoped to the business field: {parsedBody.message} regex not match success Stored values Parameter Source {external_id} {parsedBody.id} {redirect_url} {parsedBody.redirect_url} where returned Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Chytrá Autozástava (CZ) Advertiser Chytrá Autozástava Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 180 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -380, "y": 140 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/partners/leads", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Accept", "value": "application/json" }, { "key": "X-Nonce", "value": "{random_sign}" }, { "key": "X-Api-Key", "value": "{token}" }, { "key": "X-Signature", "value": "{signature}" }, { "key": "X-Timestamp", "value": "{timestamp_sign}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "phone", "value": "{data_cell_phone}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "gdpr_consent", "value": "toBool(true)" }, { "key": "partner_lead_id", "value": "{eid}" } ], "signature": { "type": "hmac_timestamp_json", "sha": "256", "delimiter": "." }, "insecure": null } } }, { "id": "1-5", "type": "setNode", "position": { "x": 40, "y": 100 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.lead_public_id}" } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": 280, "y": 100 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-6", "type": "modifyFieldNode", "position": { "x": 40, "y": 280 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.result}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.result}", "operator": "equals", "value": "duplicate_flagged", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.result}", "operator": "equals", "value": "rejected_validation", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.result}", "operator": "equals", "value": "rejected_signature", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{parsedBody.result}", "operator": "equals", "value": "rejected_rate_limit", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{status}", "operator": "regex_match", "value": "^(401|403)$", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.result}" }, { "source": "{parsedBody.error}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.error}" }, { "source": "{parsedBody.result}", "operator": "equals", "value": "duplicate_flagged", "value2": "", "modification": "replace", "pattern": "", "output": "duplicate_flagged, {parsedBody.lead_public_id}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 280, "y": 340 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-3", "type": "modifyFieldNode", "position": { "x": -380, "y": 380 }, "data": { "formData": { "active": true, "title": "Reject reason · Product mismatch", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{data_own_car}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{data_own_car}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "own_car={data_own_car}, amount={data_requested_amount}" } ] } ] } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": -540.7989821883, "y": 469.69211195929 }, "data": { "formData": { "active": true, "title": "Reject reason · Product mismatch", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{data_own_car}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{data_own_car}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "own_car={data_own_car}, amount={data_requested_amount}" } ] } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "own car + amount", "subtitle": "", "conditions": [ { "value": "{data_own_car}", "operator": "regex_not_match", "output": "^(0|no|null)$", "output2": "" }, { "value": "{data_own_car}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{data_requested_amount}", "operator": "is_greater_than", "output": "29999", "output2": "" } ] } }, { "id": "edge-1-1-1-3", "source": "1-1", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "no car", "subtitle": "", "conditions": [ { "value": "{data_own_car}", "operator": "regex_match", "output": "^(0|no|null|)$", "output2": "" } ] } }, { "id": "edge-1-1-1-4", "source": "1-1", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{data_own_car}", "operator": "regex_not_match", "output": "^(0|no|null)$", "output2": "" }, { "value": "{data_requested_amount}", "operator": "is_less_than", "output": "29999", "output2": "" } ] } }, { "id": "edge-1-2-1-5", "source": "1-2", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" }, { "value": "{parsedBody.result}", "operator": "equals", "output": "accepted", "output2": "" } ] } }, { "id": "edge-1-2-1-6", "source": "1-2", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "not accepted", "subtitle": "", "conditions": [ { "value": "{parsedBody.result}", "operator": "regex_not_match", "output": "^accepted$", "output2": "" } ] } }, { "id": "edge-1-5-1-8", "source": "1-5", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-7", "source": "1-6", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-7", "source": "1-3", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Loans secured against a vehicle. One call, a signed request, and a result field that says what happened. The product only fits someone who owns a car and wants a substantial amount. Filtering for that before the request is worth doing: it turns leads the advertiser would refuse into a Product Mismatch you can name yourself, and it keeps the rejection reports about the advertiser’s decisions rather than about your traffic. What will be needed from advertiser Key Purpose endpoint Base API URL. token API key sent in X-Api-Key. sign_secret Shared HMAC signing secret. Flows Post, POST /api/partners/leads. Creates the lead. Calls POST {endpoint}/api/partners/leads X-Api-Key: {token} X-Timestamp: {timestamp_sign} X-Signature: {signature} X-Nonce: {random_sign} Accept: application/json Content-Type: application/json format: application/json The API key has the form chzp_… and goes in X-Api-Key. Signing is optional per source but usually on. The signature is HMAC-SHA256("<X-Timestamp>.<raw body>") in hex, keyed with the shared secret. In PalDock this is the hmac_timestamp_json algorithm with SHA-256 and . as the delimiter; the node fills {signature}, {timestamp_sign} and {random_sign} itself. The secret is never sent. It lives in sign_secret and only the digest derived from it travels. The timestamp has to be within five minutes of the advertiser’s clock. The advertiser may also restrict access by IP address and apply a per-minute request limit. Request fields Field Required Value email conditionally {g_email}, required unless phone is sent phone conditionally {g_phone}, required unless email is sent first_name no {g_name_first} last_name no {g_name_last} partner_lead_id no in name only {send_id} gdpr_consent no toBool({g_consent_processing}) marketing_consent no toBool({g_consent_marketing}) loan_amount no {g_amount} loan_urgency no {g_period} or free text vehicle.brand no {g_asset_type} vehicle.model no {g_asset_variant} vehicle.year no {g_asset_year}, 1980 to 2099 vehicle.mileage_km no {g_asset_usage} source_campaign, ad, ad_set_name, platform, form_name no tracking parameters note no {g_notes} Send partner_lead_id even though it is formally optional. Without it there is nothing to match the postback against, and the conversion cannot be reconciled. Vehicle fields may be sent nested under vehicle or flat at the top level; both are accepted. Unknown parameters are ignored. loan_amount is free text rather than a number, so a range is acceptable. Enums None. Outcomes Recognised by HTTP Meaning Reject reason Frequency result: accepted 201 Accepted , common result: duplicate_flagged 200 Already seen Duplicate occasional result: rejected_validation 200 Payload refused Invalid Data occasional result: rejected_signature 401 Bad or missing signature , (technical) rare result: rejected_validation 401 Missing or invalid API key , (technical) rare result: rejected_validation 403 IP address not allowed , (technical) rare result: rejected_rate_limit 429 Too many requests , (technical) rare The last four are not rejections of the lead. They mean the integration is misconfigured or throttled, and mapping them to a reject reason hides a fault behind a normal-looking report line. Leave them uncovered: PalDock records HTTP 401, HTTP 403 and HTTP 429 on its own, and a block of those in the report is unmistakable. duplicate_flagged still returns a lead_public_id, which is worth carrying into {reason_detail} so the earlier lead can be found. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted: {status} equals 201 {parsedBody.result} equals accepted Refused, scoped to the business field, so only the advertiser’s own answers arrive here: {parsedBody.result} regex not match ^accepted$ Optionally, filter before the request: own vehicle regex not match ^(0|no|null|)$ {g_amount} is greater than 29999 Each filtered path ends in a Reject reason node mapping Product Mismatch, with the values that failed carried into {reason_detail}. Stored values Parameter Source {external_id} {parsedBody.lead_public_id} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to CoolCredit (CZ) Advertiser CoolCredit Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -430, "y": -20 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "4" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "5" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "6" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "6" } ] }, { "fieldName": "{data_employed_time}", "fields": [ { "source": "{data_employed_time}", "operator": "equals", "value": "3-month", "value2": "", "modification": "replace", "pattern": "", "output": "lessthan3months" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-year", "value2": "", "modification": "replace", "pattern": "", "output": "lessthan1year" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-2-year", "value2": "", "modification": "replace", "pattern": "", "output": "1to2years" }, { "source": "{data_employed_time}", "operator": "equals", "value": "2-5-year", "value2": "", "modification": "replace", "pattern": "", "output": "3to5years" }, { "source": "{data_employed_time}", "operator": "equals", "value": "5-year-plus", "value2": "", "modification": "replace", "pattern": "", "output": "morethan5years" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "owner" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "sublet" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "parents" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "sublet" } ] }, { "fieldName": "{data_bank_code}", "fields": [ { "source": "{data_bank_code}", "operator": "equals", "value": "0100", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_bank_code}", "operator": "equals", "value": "0300", "value2": "", "modification": "replace", "pattern": "", "output": "6" }, { "source": "{data_bank_code}", "operator": "equals", "value": "0600", "value2": "", "modification": "replace", "pattern": "", "output": "5" }, { "source": "{data_bank_code}", "operator": "equals", "value": "0710", "value2": "", "modification": "replace", "pattern": "", "output": "8" }, { "source": "{data_bank_code}", "operator": "equals", "value": "0800", "value2": "", "modification": "replace", "pattern": "", "output": "4" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2010", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2020", "value2": "", "modification": "replace", "pattern": "", "output": "9" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2030", "value2": "", "modification": "replace", "pattern": "", "output": "10" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2050", "value2": "", "modification": "replace", "pattern": "", "output": "11" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2060", "value2": "", "modification": "replace", "pattern": "", "output": "12" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2070", "value2": "", "modification": "replace", "pattern": "", "output": "13" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2100", "value2": "", "modification": "replace", "pattern": "", "output": "14" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2200", "value2": "", "modification": "replace", "pattern": "", "output": "15" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2210", "value2": "", "modification": "replace", "pattern": "", "output": "16" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2220", "value2": "", "modification": "replace", "pattern": "", "output": "17" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2230", "value2": "", "modification": "replace", "pattern": "", "output": "18" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2240", "value2": "", "modification": "replace", "pattern": "", "output": "19" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2250", "value2": "", "modification": "replace", "pattern": "", "output": "20" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2260", "value2": "", "modification": "replace", "pattern": "", "output": "54" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2275", "value2": "", "modification": "replace", "pattern": "", "output": "55" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2310", "value2": "", "modification": "replace", "pattern": "", "output": "21" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2600", "value2": "", "modification": "replace", "pattern": "", "output": "22" }, { "source": "{data_bank_code}", "operator": "equals", "value": "2700", "value2": "", "modification": "replace", "pattern": "", "output": "23" }, { "source": "{data_bank_code}", "operator": "equals", "value": "3030", "value2": "", "modification": "replace", "pattern": "", "output": "24" }, { "source": "{data_bank_code}", "operator": "equals", "value": "3060", "value2": "", "modification": "replace", "pattern": "", "output": "56" }, { "source": "{data_bank_code}", "operator": "equals", "value": "3500", "value2": "", "modification": "replace", "pattern": "", "output": "25" }, { "source": "{data_bank_code}", "operator": "equals", "value": "4000", "value2": "", "modification": "replace", "pattern": "", "output": "26" }, { "source": "{data_bank_code}", "operator": "equals", "value": "4300", "value2": "", "modification": "replace", "pattern": "", "output": "27" }, { "source": "{data_bank_code}", "operator": "equals", "value": "5000", "value2": "", "modification": "replace", "pattern": "", "output": "28" }, { "source": "{data_bank_code}", "operator": "equals", "value": "5400", "value2": "", "modification": "replace", "pattern": "", "output": "29" }, { "source": "{data_bank_code}", "operator": "equals", "value": "5500", "value2": "", "modification": "replace", "pattern": "", "output": "2" }, { "source": "{data_bank_code}", "operator": "equals", "value": "5800", "value2": "", "modification": "replace", "pattern": "", "output": "30" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6000", "value2": "", "modification": "replace", "pattern": "", "output": "31" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6200", "value2": "", "modification": "replace", "pattern": "", "output": "33" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6210", "value2": "", "modification": "replace", "pattern": "", "output": "34" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6300", "value2": "", "modification": "replace", "pattern": "", "output": "35" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6363", "value2": "", "modification": "replace", "pattern": "", "output": "75" }, { "source": "{data_bank_code}", "operator": "equals", "value": "6700", "value2": "", "modification": "replace", "pattern": "", "output": "36" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7910", "value2": "", "modification": "replace", "pattern": "", "output": "38" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7940", "value2": "", "modification": "replace", "pattern": "", "output": "39" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7950", "value2": "", "modification": "replace", "pattern": "", "output": "40" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7960", "value2": "", "modification": "replace", "pattern": "", "output": "41" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7970", "value2": "", "modification": "replace", "pattern": "", "output": "42" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7980", "value2": "", "modification": "replace", "pattern": "", "output": "43" }, { "source": "{data_bank_code}", "operator": "equals", "value": "7990", "value2": "", "modification": "replace", "pattern": "", "output": "44" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8030", "value2": "", "modification": "replace", "pattern": "", "output": "45" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8040", "value2": "", "modification": "replace", "pattern": "", "output": "46" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8060", "value2": "", "modification": "replace", "pattern": "", "output": "47" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8090", "value2": "", "modification": "replace", "pattern": "", "output": "48" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8150", "value2": "", "modification": "replace", "pattern": "", "output": "49" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8190", "value2": "", "modification": "replace", "pattern": "", "output": "57" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8198", "value2": "", "modification": "replace", "pattern": "", "output": "58" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8199", "value2": "", "modification": "replace", "pattern": "", "output": "59" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8200", "value2": "", "modification": "replace", "pattern": "", "output": "50" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8215", "value2": "", "modification": "replace", "pattern": "", "output": "60" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8220", "value2": "", "modification": "replace", "pattern": "", "output": "61" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8230", "value2": "", "modification": "replace", "pattern": "", "output": "62" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8240", "value2": "", "modification": "replace", "pattern": "", "output": "63" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8250", "value2": "", "modification": "replace", "pattern": "", "output": "64" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8255", "value2": "", "modification": "replace", "pattern": "", "output": "65" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8260", "value2": "", "modification": "replace", "pattern": "", "output": "66" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8265", "value2": "", "modification": "replace", "pattern": "", "output": "67" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8270", "value2": "", "modification": "replace", "pattern": "", "output": "68" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8272", "value2": "", "modification": "replace", "pattern": "", "output": "69" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8280", "value2": "", "modification": "replace", "pattern": "", "output": "70" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8283", "value2": "", "modification": "replace", "pattern": "", "output": "71" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8292", "value2": "", "modification": "replace", "pattern": "", "output": "72" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8293", "value2": "", "modification": "replace", "pattern": "", "output": "73" }, { "source": "{data_bank_code}", "operator": "equals", "value": "8294", "value2": "", "modification": "replace", "pattern": "", "output": "74" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "25000", "value2": "", "modification": "replace", "pattern": "", "output": "25000" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -200, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v2/registrations", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "token", "value": "{token}" } ], "body": [ { "key": "nin", "value": "{data_nin}" }, { "key": "bank", "value": "{data_bank_code}" }, { "key": "city", "value": "{data_city}" }, { "key": "days", "value": "{data_period}" }, { "key": "name", "value": "{data_first_name}" }, { "key": "costs", "value": "{data_expenses}" }, { "key": "email", "value": "{data_email}" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "street", "value": "{data_street}" }, { "key": "housing", "value": "{data_home_status}" }, { "key": "surname", "value": "{data_last_name}" }, { "key": "zipCode", "value": "{data_zip}" }, { "key": "employer", "value": "{data_employer}" }, { "key": "ipAddress", "value": "{ip_address}" }, { "key": "netIncome", "value": "{data_monthly_income}" }, { "key": "moneySource", "value": "{data_income_type}" }, { "key": "phoneNumber", "value": "{data_cell_phone}" }, { "key": "deliveryCity", "value": "{data_contact_city}" }, { "key": "idCardNumber", "value": "{data_identity_card_number}" }, { "key": "streetNumber", "value": "{data_house_number}" }, { "key": "workingYears", "value": "{data_employed_time}" }, { "key": "accountNumber", "value": "{data_account_number}" }, { "key": "deliveryStreet", "value": "{data_contact_street}" }, { "key": "selfEmployerIc", "value": "{data_company_number_imported}" }, { "key": "deliveryZipCode", "value": "{data_contact_zip}" }, { "key": "employerPosition", "value": "{data_job_title}" }, { "key": "employerPhoneNumber", "value": "{data_employer_phone}" }, { "key": "deliveryStreetNumber", "value": "{data_contact_house_number}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 60, "y": -40 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.data.id}" }, { "key": "{redirect_url}", "value": "{parsedBody.data.redirect_url}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 300, "y": -40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 60, "y": 160 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.description}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.data.description}", "operator": "equals", "value": "KO", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.data.description}", "operator": "contains", "value": "Scoring", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.data.description}", "operator": "contains", "value": "Validation error", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{status}", "operator": "equals", "value": "409", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}" }, { "source": "{parsedBody.data.description}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.data.description}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 300, "y": 160 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "created", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" }, { "value": "{parsedBody.data.redirect_url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "not created", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "regex_not_match", "output": "^201$", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Single-step registration. There is no ping, one call creates the customer and returns the decision along with the redirect URL. The thing to know before building this: CoolCredit answers business rejections with HTTP 241, a status code that does not exist in the standard. It is a real answer, not a fault, and it carries the reason. What will be needed from advertiser Key Purpose endpoint Base API URL. token Token sent in the query string. Flows Post, POST /api/v2/registrations?token={token}. Creates the registration and decides in the same call. Calls POST {endpoint}/api/v2/registrations?token={token} Content-Type: application/json format: application/json The token goes in the query string, not a header. Request fields Field Required Value name yes {g_name_first} surname yes {g_name_last} nin yes {g_id_national_number} idCardNumber yes {g_id_card_number} phoneNumber yes {g_phone} email yes {g_email} street yes {g_address_street} streetNumber yes {g_address_street_number} city yes {g_address_city} zipCode yes {g_address_zip} deliveryStreet no {g_address_contact_street} deliveryStreetNumber no {g_address_contact_street_number} deliveryCity no {g_address_contact_city} deliveryZipCode no {g_address_contact_zip} moneySource yes {g_fin_type}, see enums netIncome yes {g_fin_income} costs no {g_fin_expenses} workingYears yes {g_employ_time}, see enums housing yes {g_home_type}, see enums accountNumber yes {g_bank_account_number} bank yes {g_bank_account_code}, see enums amount yes {g_amount}, capped at 25 000 days yes {g_period} employer no {g_employer_name} employerPosition no {g_employ_position} employerPhoneNumber no {g_employer_phone} selfEmployerIc self-employed {g_company_registration} ipAddress yes {ip_address} accountNumber and bank are separate fields, the account number goes in without the bank code, and the code becomes a numeric bank ID. On capping the amount Where a request exceeds the advertiser’s maximum, send the maximum rather than the requested figure, but agree it with them first. Translating a higher request down is right only when they would otherwise reject the lead outright. Where they would have made a smaller offer on their own, send what the applicant actually asked for and let them answer. This is the one place the general rule bends: amount, term and product are the request itself, so they are normally passed through untouched. Enums bank is a numeric ID, not the Czech bank code. GET /api/v1/banks?token=… returns the current list; fetch it once and write the mapping into the blueprint rather than calling it per lead. A wrong ID is rejected with Bank is id not valid. The mapping is long, roughly seventy Czech bank codes. Two warnings about writing it: Put the fallback first in the section, not last. A fallback placed last with the field as its own source re-reads the original four-digit code and overwrites every mapping that just succeeded. This has happened, silently, across hundreds of leads. Do not add a repair regex for the bank code itself. If codes arrive malformed, that is the form’s validation to fix, once, for every advertiser. moneySource: numeric, 1 employed, 3 self-employed, 4 maternity, 5 pension, 6 unemployed or other. workingYears and housing vary by contract, one configuration takes the form’s own values unchanged, another takes CoolCredit’s labels. Check which one the account uses before mapping. Outcomes Recognised by HTTP Meaning Reject reason Frequency status.message ~ Created 201 Accepted , occasional data.description: KO 241 Refused, no reason given Unspecified common data.description: Scoring 241 Refused by scoring Poor Credit common data.description ~ Validation error 400 Payload refused, field named Invalid Data occasional data.description ~ Registration processing 409 An earlier registration is still running Duplicate rare The validation messages name the field: IdCardNumber is not valid, ZipCode is not valid, AccountNumber is not valid, Bank is id not valid. Choose bank id according to api documentation. Pass the whole description through in {reason_detail}; a run of one field name is a form problem, not an advertiser problem. KO is the largest bucket and means nothing more than “no”. Unspecified, every time not Not Eligible, because no condition was named. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted, both parts checked on the same connection: {status} equals 201 {parsedBody.status.message} contains Created Everything else that is an answer. The catch-all is paired with the success status code so that only CoolCredit’s own responses can reach it: {status}|{parsedBody.status.message} regex not match ^201\|.*Created.*$ 241, 400 and 409 all carry a documented business result in the body, which is why they are branched rather than left to Dead End. A bare 401 or 5xx gets no branch. Stored values Parameter Source {external_id} {parsedBody.data.id} {redirect_url} {parsedBody.data.redirect_url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to CreditGO (CZ) Advertiser CreditGO Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Platform CreditOnline Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint Blueprint for new customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -650, "y": 120 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -500, "y": -160 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -520, "y": 120 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "OSVČ" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "Mateřská dovolená" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "Důchodce" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "Nezaměstnaný" } ] }, { "fieldName": "{data_different_contact_address}", "fields": [ { "source": "{data_different_contact_address}", "operator": "regex_match", "value": "(?i)^(true|yes|ano)$", "value2": "", "modification": "replace", "pattern": "", "output": "0" }, { "source": "{data_different_contact_address}", "operator": "regex_match", "value": "(?i)^(false|no|ne|null)$", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_different_contact_address}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "1" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "30000", "value2": "", "modification": "replace", "pattern": "", "output": "30000" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_expenses}", "fields": [ { "source": "{data_expenses}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_company_number_imported}", "fields": [ { "source": "{data_company_number_imported}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_job_title}", "fields": [ { "source": "{data_job_title}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -362.25796425835, "y": 170.73515691127 }, "data": { "formData": { "active": true, "title": "Create", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.registerClient", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.chk3", "value": "1" }, { "key": "data.chk5", "value": "1" }, { "key": "data.chk8", "value": "1" }, { "key": "data.chk9", "value": "1" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.city2", "value": "{data_contact_city}" }, { "key": "data.costs", "value": "{data_expenses}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.house2", "value": "{data_contact_house_number}" }, { "key": "data.income", "value": "{data_monthly_income}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.address2", "value": "{data_contact_street}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.zipcode2", "value": "{data_contact_zip}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.workplace", "value": "{data_employer}" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.check_adresa", "value": "{data_different_contact_address}" }, { "key": "data.company_code", "value": "{data_company_number_imported}" }, { "key": "data.other_income", "value": "{data_income_type}" }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" }, { "key": "data.workplace_position", "value": "{data_job_title}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": -200, "y": 70 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.customer_id}" }, { "key": "{customer_id}", "value": "{parsedBody.customer_id}" } ] } } }, { "id": "1-6", "type": "httpNode", "position": { "x": -40, "y": 70 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/credits/application", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "apiLan", "value": "cz" }, { "key": "period", "value": "{data_period}" }, { "key": "_method", "value": "post" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "30000" }, { "key": "customerId", "value": "{customer_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-8", "type": "setNode", "position": { "x": 120, "y": 20 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 120.54856453418, "y": 180 }, "data": { "formData": { "active": true, "title": "Reject reason · Create", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.err}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 300, "y": 180 }, "data": { "formData": { "active": true, "title": "Rejected · Create", "subtitle": "", "success": "failed" } } }, { "id": "1-10", "type": "endNode", "position": { "x": 300, "y": 20 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -340, "y": -160 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "modifyFieldNode", "position": { "x": -160, "y": -80 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.personalData.person_code}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.email}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.mob_phone}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.id_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.account_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Application|Registrator|Klient)$", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Request|Loan)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Rejected", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS|BadScore)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(BlackList|BlockList)$", "value2": "", "modification": "replace", "pattern": "", "output": "Blacklist" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-5", "type": "endNode", "position": { "x": 40, "y": -80 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-4", "type": "endNode", "position": { "x": 40, "y": -220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-9", "type": "modifyFieldNode", "position": { "x": 120, "y": 300 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.status}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-11", "type": "endNode", "position": { "x": 300, "y": 300 }, "data": { "formData": { "active": true, "title": "Rejected · Post", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "regex_match", "output": "^1$", "output2": "" }, { "value": "{parsedBody.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}|{parsedBody.customer_id}", "operator": "regex_not_match", "output": "^1\\|[^|]+$", "output2": "" }, { "value": "{parsedBody.err}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-6-1-9", "source": "1-6", "target": "1-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "regex_not_match", "output": "^success$", "output2": "" } ] } }, { "id": "edge-1-8-1-10", "source": "1-8", "target": "1-10", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "(?:\"(?:person_code|email|mob_phone|id_number|account_number)\"\\s*:\\s*\"registered\"|\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+)|\"addinfo\"\\s*:\\s*\"(?:Application|Registrator|Klient|Request|Loan|Rejected|Loan creation declined|Registration declined by CSAS|Request declined by CSAS|BadScore|BlackList|BlockList)\"|\"person_code\"\\s*:\\s*\"age_check_failed\")", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "regex_match", "output": "^1$", "output2": "" }, { "value": "{parsedBody.personalData.person_code}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.email}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.mob_phone}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.id_number}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.account_number}", "operator": "equals", "output": "notFound", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-9-1-11", "source": "1-9", "target": "1-11", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Bueprint for registered customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -450, "y": 130 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -450, "y": -150 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -300, "y": 130 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "30000", "value2": "", "modification": "replace", "pattern": "", "output": "30000" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -140, "y": 130 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/credits/application", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "apiLan", "value": "cz" }, { "key": "period", "value": "{data_period}" }, { "key": "_method", "value": "post" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "30000" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 20, "y": 70 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 20, "y": 190 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.status}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 200, "y": 190 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-6", "type": "endNode", "position": { "x": 200, "y": 70 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -280, "y": -150 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "setNode", "position": { "x": -100, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{customer_id}", "value": "{parsedBody.personalData.customer_id}" }, { "key": "{external_id}", "value": "{parsedBody.personalData.customer_id}" } ] } } }, { "id": "2-4", "type": "modifyFieldNode", "position": { "x": -100, "y": -80 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "notFound", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.person_code}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.email}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.mob_phone}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.id_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.account_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Application|Registrator|Klient)$", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Request|Loan)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Rejected", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS|BadScore)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(BlackList|BlockList)$", "value2": "", "modification": "replace", "pattern": "", "output": "Blacklist" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 100, "y": -80 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-5", "type": "endNode", "position": { "x": 100, "y": -220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "regex_not_match", "output": "^success$", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "regex_match", "output": "^1$", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "contains", "output": "Registrator", "output2": "" }, { "value": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}|{parsedBody.personalData.addinfo}|{parsedBody.personalData.customer_id}", "operator": "regex_not_match", "output": "^1\\|.*Registrator.*\\|[^|]+$", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "(?:\"person_code\"\\s*:\\s*\"notFound\"|\"(?:person_code|email|mob_phone|id_number|account_number)\"\\s*:\\s*\"registered\"|\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+)|\"addinfo\"\\s*:\\s*\"(?:Application|Registrator|Klient|Request|Loan|Rejected|Loan creation declined|Registration declined by CSAS|Request declined by CSAS|BadScore|BlackList|BlockList)\"|\"person_code\"\\s*:\\s*\"age_check_failed\")", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Blueprint for repeated customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -450, "y": 130 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -450, "y": -150 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -300, "y": 130 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "30000", "value2": "", "modification": "replace", "pattern": "", "output": "30000" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -140, "y": 130 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/credits/application", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "apiLan", "value": "cz" }, { "key": "period", "value": "{data_period}" }, { "key": "_method", "value": "post" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "30000" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 20, "y": 70 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 20, "y": 190 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.status}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 200, "y": 190 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-6", "type": "endNode", "position": { "x": 200, "y": 70 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -280, "y": -150 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "setNode", "position": { "x": -100, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{customer_id}", "value": "{parsedBody.personalData.customer_id}" }, { "key": "{external_id}", "value": "{parsedBody.personalData.customer_id}" } ] } } }, { "id": "2-4", "type": "modifyFieldNode", "position": { "x": -100, "y": -80 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "notFound", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.person_code}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.email}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.mob_phone}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.id_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.account_number}", "operator": "contains", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Application|Registrator|Klient)$", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Request|Loan)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Rejected", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS|BadScore)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(BlackList|BlockList)$", "value2": "", "modification": "replace", "pattern": "", "output": "Blacklist" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 100, "y": -80 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-5", "type": "endNode", "position": { "x": 100, "y": -220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "regex_not_match", "output": "^success$", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "regex_match", "output": "^1$", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "contains", "output": "Klient", "output2": "" }, { "value": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}|{parsedBody.personalData.addinfo}|{parsedBody.personalData.customer_id}", "operator": "regex_not_match", "output": "^1\\|.*Klient.*\\|[^|]+$", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "(?:\"person_code\"\\s*:\\s*\"notFound\"|\"(?:person_code|email|mob_phone|id_number|account_number)\"\\s*:\\s*\"registered\"|\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+)|\"addinfo\"\\s*:\\s*\"(?:Application|Registrator|Klient|Request|Loan|Rejected|Loan creation declined|Registration declined by CSAS|Request declined by CSAS|BadScore|BlackList|BlockList)\"|\"person_code\"\\s*:\\s*\"age_check_failed\")", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details CreditGO runs on a CreditOnline white-label backend and is split into three client flows: new clients, registered clients (Registrator) and repeated clients (Klient). This page is self-contained: it describes the RPC envelope, the CreditGO-specific customer states and the application rules used by those current flows. The important distinction is that a successful CreditGO application does not require a redirect URL. Real Klient responses can create a credit with data.status: success and a non-empty credit_id while data.url is empty. What will be needed from advertiser Key Purpose endpoint CreditOnline tenant API base URL. token Application API key used as apiKey. username RPC login. password RPC password. partner_id Broker identifier sent as brokerId. Flows New clients — Ping, POST /?RPC=agents.checkPersonalData. A genuinely new client is one where every checked identity field is notFound. New clients — Post, registerClient first, then POST /api/v1.0/credits/application. The customer ID from registration is carried into the application. Registered clients — Ping, the same check, but success requires addinfo containing Registrator and a non-empty customer_id. Post skips registration and applies directly. Repeated clients — Ping, success requires addinfo containing Klient and a non-empty customer_id. Post skips registration and applies directly. Calls POST {endpoint}/?RPC=agents.checkPersonalData POST {endpoint}/?RPC=agents.registerClient POST {endpoint}/api/v1.0/credits/application?… The RPC calls use format: login-data-pass and Content-Type: application/x-www-form-urlencoded; charset=UTF-8. Their form body has exactly three top-level keys: login, pass and data; the actual advertiser payload is written as data.* fields. All client flows send {username} / {password} as login / pass. Do not build this form envelope manually. The /credits/application call is a plain query-string POST and uses {token} as apiKey and {partner_id} as brokerId. Response model checkPersonalData normally answers with HTTP 200 even when the person must be rejected, so HTTP status alone is never the Ping decision. The useful payload is ok plus personalData. The identity fields inside personalData are returned as states such as notFound or registered; addinfo and an optional customer_id describe the advertiser-side customer state. The current flows compare ok with regex match ^1$ because production can return it in a representation that should not be treated as a strict string-only value. For CreditGO, the client flow matters: new clients accept only an all-notFound person, registered clients accept addinfo containing Registrator, and repeated clients accept addinfo containing Klient. Request and Loan mean an open/existing credit state and are terminal. Scoring and blacklist states are mapped in Outcomes below. Do not import generic CreditOnline states that are not present in the current CreditGO branches. Authentication failure can itself arrive as HTTP 200 with an err payload and no usable ok/personalData. That is a credentials/technical failure, not a business rejection. The Ping branches explicitly require ok plus the expected customer-state fields, so such a response cannot satisfy them. registerClient returns a customer_id on success. Any URL from registration is not the final redirect; the conversion happens only on /credits/application. Registration failures use an err payload; only the concrete error texts listed in Outcomes are converted into business reject reasons. The application response has a top-level status and a nested data object. A created credit is recognised by nested data.status: success plus a non-empty credit_id. data.url may be empty on a valid CreditGO conversion, especially for registered or repeated clients, so the success branch must not require a redirect URL. Request fields Ping — all client flows Field Required Value realname yes {g_name_first} surname yes {g_name_last} email yes {g_email} mob_phone yes {g_phone} person_code yes {g_id_national_number} id_number yes {g_id_card_number} account_number yes {g_bank_account_number}/{g_bank_account_code} address yes {g_address_street} house yes {g_address_street_number} city yes {g_address_city} zipcode yes {g_address_zip} Register client — new clients The request carries the same identity/address data plus income and consent data. The fields that matter for the current mapping are: Field Required Value check_adresa yes inverse of the “contact address differs” flag: 1 same, 0 different address2, house2, city2, zipcode2 when different contact address fields other_income yes mapped income type, see transforms income yes {g_fin_income} costs no {g_fin_expenses} workplace no {g_employer_name} workplace_position no {g_employ_position} company_code self-employed {g_company_registration} account_number yes {g_bank_account_number}/{g_bank_account_code} ip yes {ip_address} chk3, chk5, chk8, chk9 yes consent/AML flags defined by the current blueprint Empty optional contact, expenses, employer, company-number and job-title fields are omitted rather than sent empty. Application Parameter Value customerId customer ID from Ping or registerClient amount capped request amount, max 30000 period {g_period} maxAmount 30000 account_number {g_bank_account_number}/{g_bank_account_code} brokerId {partner_id} _method post apiLan cz apiKey {token} Transforms New clients map income types before registration: full-time → Zaměstnanec, self-employed → OSVČ, parental → Mateřská dovolená, pension → Důchodce, unemployed → Nezaměstnaný. The “contact address differs” flag is inverted for check_adresa: true/different becomes 0, false/same becomes 1. Every Post caps {g_amount} at 30000 before the application. Registered and repeated clients only need this cap; they do not run the registration mappings. Outcomes Recognised by Meaning Reject reason all checked identity fields notFound New clients Ping succeeds addinfo contains Registrator + customer_id Registered clients Ping succeeds addinfo contains Klient + customer_id Repeated clients Ping succeeds status: 200, data.status: success, non-empty credit_id Application created any checked identity field registered, or customer_id, or addinfo: Application/Registrator/Klient in the wrong client flow Already known / wrong client flow Duplicate addinfo: Request or Loan Open request or loan Existing Customer addinfo: Registration declined by CSAS, Request declined by CSAS, BadScore Scoring refusal Poor Credit addinfo: BlackList or BlockList Blocked client Blacklist person_code: age_check_failed Age check failed Age addinfo: Loan creation declined or Rejected Refused without a usable reason Unspecified all-notFound person in the registered or repeated clients flow Wrong client state Product Mismatch non-success data.status at application Business refusal Unspecified Technical non-200 responses are intentionally not converted into business rejects. {reason_detail} should carry the raw {body}. Branching New clients Ping: {status} equals 200 {parsedBody.ok} regex match ^1$ {parsedBody.personalData.person_code} equals notFound {parsedBody.personalData.email} equals notFound {parsedBody.personalData.mob_phone} equals notFound {parsedBody.personalData.id_number} equals notFound {parsedBody.personalData.account_number} equals notFound Registered clients Ping: {status} equals 200 {parsedBody.ok} regex match ^1$ {parsedBody.personalData.addinfo} contains Registrator {parsedBody.personalData.customer_id} is not empty Repeated clients are identical except for contains Klient. Application success, all client flows: {status} equals 200 {parsedBody.status} equals 200 {parsedBody.data.status} equals success {parsedBody.data.credit_id} is not empty Do not add data.url is not empty to that success condition. Stored values Parameter Source {customer_id} / temporary {external_id} customer_id from Ping or registration {external_id} {parsedBody.data.credit_id} after the application {redirect_url} {parsedBody.data.url} when returned Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to CreditKasa (CZ) Advertiser CreditKasa Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 400 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "setNode", "position": { "x": -450, "y": 400 }, "data": { "formData": { "active": true, "title": "Auth", "subtitle": "", "fields": [ { "key": "{auth_raw}", "value": "{username}:{password}" } ] } } }, { "id": "1-3", "type": "modifyFieldNode", "position": { "x": -260, "y": 400 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{auth}", "fields": [ { "source": "{auth_raw}", "operator": "always", "value": "", "value2": "", "modification": "to_base64", "pattern": "", "output": "" } ] }, { "fieldName": "{data_nin}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "(\\d{6})(\\d{3,4})", "output": "$1/$2" } ] } ] } } }, { "id": "1-4", "type": "httpNode", "position": { "x": -69.523413111342, "y": 397.93652445369 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/leadpartnerapi", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "X-Request-ID", "value": "{eid}" }, { "key": "Authorization", "value": "Basic {auth}" } ], "query": [], "body": [ { "key": "method", "value": "checkDuplicate" }, { "key": "customer-personcode", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-5", "type": "setNode", "position": { "x": 142.27575442248, "y": 312.75130072841 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.lead-id}" } ] } } }, { "id": "1-6", "type": "modifyFieldNode", "position": { "x": 121.64099895942, "y": 479.36524453694 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.err}", "operator": "equals", "value": "duplicate-customer", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 309.36628511967, "y": 324.44432882414 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-8", "type": "endNode", "position": { "x": 327.24973985432, "y": 486.93132154006 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "setNode", "position": { "x": -450, "y": 40 }, "data": { "formData": { "active": true, "title": "Auth", "subtitle": "", "fields": [ { "key": "{auth_raw}", "value": "{username}:{password}" } ] } } }, { "id": "2-3", "type": "modifyFieldNode", "position": { "x": -260, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{auth}", "fields": [ { "source": "{auth_raw}", "operator": "always", "value": "", "value2": "", "modification": "to_base64", "pattern": "", "output": "" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_less_than", "value": "5000", "value2": "", "modification": "replace", "pattern": "", "output": "5000" } ] }, { "fieldName": "{data_nin}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "(\\d{6})(\\d{3,4})", "output": "$1/$2" } ] }, { "fieldName": "{data_cell_phone}", "fields": [ { "source": "{data_cell_phone}", "operator": "regex_match", "value": "^\\d{9}$", "value2": "", "modification": "regex_replace", "pattern": "^(\\d{9})$", "output": "+420$1" }, { "source": "{data_cell_phone}", "operator": "regex_match", "value": "^420\\d{9}$", "value2": "", "modification": "regex_replace", "pattern": "^(420\\d{9})$", "output": "+$1" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "HOME_OWNER" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "CO_OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE_BENEFIT" } ] }, { "fieldName": "{data_employed_time}", "fields": [ { "source": "{data_employed_time}", "operator": "equals", "value": "3-month", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-year", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-2-year", "value2": "", "modification": "replace", "pattern": "", "output": "4" }, { "source": "{data_employed_time}", "operator": "equals", "value": "2-5-year", "value2": "", "modification": "replace", "pattern": "", "output": "5" }, { "source": "{data_employed_time}", "operator": "equals", "value": "5-year-plus", "value2": "", "modification": "replace", "pattern": "", "output": "8" } ] } ] } } }, { "id": "2-4", "type": "httpNode", "position": { "x": -112.85639958377, "y": 40.687825182102 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/leadpartnerapi", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Basic {auth}" } ], "query": [], "body": [ { "key": "pin", "value": "{data_nin}" }, { "key": "email", "value": "{data_email}" }, { "key": "phone", "value": "{data_cell_phone}" }, { "key": "method", "value": "registerCustomer" }, { "key": "housing", "value": "{data_home_status}" }, { "key": "lead-id", "value": "{external_id}" }, { "key": "lastname", "value": "{data_last_name}" }, { "key": "passport", "value": "{data_identity_card_number}" }, { "key": "firstname", "value": "{data_first_name}" }, { "key": "loan-term", "value": "{data_period}" }, { "key": "address-zip", "value": "{data_zip}" }, { "key": "company-ico", "value": "{data_company_number_imported}" }, { "key": "loan-amount", "value": "{data_requested_amount}" }, { "key": "address-city", "value": "{data_city}" }, { "key": "company-name", "value": "{data_employer}" }, { "key": "employed-for", "value": "{data_employed_time}" }, { "key": "income-source", "value": "{data_income_type}" }, { "key": "address-number", "value": "{data_house_number}" }, { "key": "address-street", "value": "{data_street}" }, { "key": "employer-phone", "value": "{data_employer_phone}" }, { "key": "monthly-income", "value": "{data_monthly_income}" }, { "key": "type-of-income", "value": "{data_job_title}" }, { "key": "employer-address", "value": "{data_employer_address}" }, { "key": "monthly-expenses", "value": "{data_expenses}" }, { "key": "contact-address-zip", "value": "{data_contact_zip}" }, { "key": "contact-address-city", "value": "{data_contact_city}" }, { "key": "contact-address-number", "value": "{data_contact_house_number}" }, { "key": "contact-address-street", "value": "{data_contact_street}" } ], "signature": null, "insecure": null } } }, { "id": "2-5", "type": "setNode", "position": { "x": 138.83662851197, "y": -47.936524453694 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.return-url}" }, { "key": "{external_id}", "value": "{parsedBody.lead-id}" } ] } } }, { "id": "2-6", "type": "modifyFieldNode", "position": { "x": 99.525379498684, "y": 158.52731448446 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.err}", "operator": "equals", "value": "unsuccessful", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.err}", "operator": "equals", "value": "duplicate-customer", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 359.57752341311, "y": -30.740894901145 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-8", "type": "endNode", "position": { "x": 326.56191467222, "y": 142.43392299688 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-5", "source": "1-4", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.result}", "operator": "equals", "output": "1", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.err}", "operator": "equals", "output": "duplicate-customer", "output2": "" } ] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-5", "source": "2-4", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.result}", "operator": "equals", "output": "1", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.err}", "operator": "regex_match", "output": "^(unsuccessful|duplicate-customer)$", "output2": "" } ] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-8", "source": "2-6", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Both steps are POSTs to the same URL; the method field in the body says which operation is meant. Everything comes back as HTTP 200, including refusals. The decision is in result. What will be needed from advertiser Key Purpose endpoint Base API URL. username Basic Auth username. password Basic Auth password. Flows Ping, method: checkDuplicate. Asks whether the national ID is already on file. Returns a lead-id that the post reuses. Post, method: registerCustomer. Registers and decides. Returns return-url. Calls POST {endpoint}/leadpartnerapi Authorization: Basic base64({username}:{password}) Content-Type: application/json format: application/json Build the Basic header from the two halves at run time rather than storing an encoded blob: Set {auth0} = {username}:{password} Modify {auth} ← {auth0}, to_base64 HTTP Authorization: Basic {auth} Wrong credentials come back as {"result": "-1", "err": "wrong credentials"} with HTTP 200. That is a broken integration, not a rejected lead, do not map it to a reject reason. Request fields Ping Field Required Value method yes checkDuplicate customer-personcode yes {g_id_national_number} with the slash Post Field Required Value method yes registerCustomer lead-id no {custom_lead_id} from the ping pin yes {g_id_national_number} with the slash passport yes {g_id_card_number} firstname yes {g_name_first} lastname yes {g_name_last} email yes {g_email} phone yes {g_phone} as +420999999999 loan-amount yes {g_amount}, minimum 5 000 loan-term yes {g_period}, 1–70 or 180 monthly-income yes {g_fin_income} monthly-expenses no {g_fin_expenses} income-source no {g_fin_type}, see enums employed-for no {g_employ_time} company-name no {g_employer_name} company-ico no {g_company_registration} employer-address no {g_employer_address} employer-phone no {g_employer_phone} address-street yes {g_address_street} address-number yes {g_address_street_number} address-city yes {g_address_city} address-zip yes {g_address_zip} contact-address-street no {g_address_contact_street} contact-address-number no {g_address_contact_street_number} contact-address-city no {g_address_contact_city} contact-address-zip no {g_address_contact_zip} housing no {g_home_type}, see enums pin and customer-personcode need the slash: 541203/1234. The form produces plain digits, so this is one of the few transformations that genuinely belongs in the integration: {g_id_national_number} always regex_replace (\d{6})(\d{3,4}) → $1/$2 phone needs the +420 prefix. Add it conditionally, so a number that already carries it is not prefixed twice. Enums income-source: EMPLOYED, PART_TIME_EMPLOYMENT, SELF_EMPLOYED, PENSION, MATERNITY_LEAVE, BENEFITS, SAVINGS, STUDENT, UNEMPLOYED, OTHER. housing: HOME_OWNER, TENANT, CO_OWNED, EMPLOYEE_BENEFIT. The advertiser also accepts sex, marital-status, dependents-count, industry, education, execution, insolvency and third-parties-debt, all optional. Send them only where the form actually collects them. Outcomes result is the decision: 1 accepted, 0 refused. err is empty on success and names the problem otherwise. Recognised by HTTP Meaning Reject reason Frequency result: 1, err: "" 200 Accepted , common err: duplicate-customer 200 Already on file Existing Customer occasional err: unsuccessful 200 Refused, no reason given Unspecified common err: wrong credentials 200 Bad credentials , (technical) never in normal operation The vocabulary is genuinely this small. unsuccessful accounts for nearly every refusal at the post and says nothing at all, Unspecified. At the ping, duplicate-customer comes back with lead-id: "0". At the post it comes back with a real lead-id. Neither is usable; the answer is the same either way. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, new person: {status} equals 200 {parsedBody.result} equals 1 Ping, duplicate: {status} equals 200 {parsedBody.err} equals duplicate-customer Post, accepted: {status} equals 200 {parsedBody.result} equals 1 Post, refused: {status} equals 200 {parsedBody.err} regex match ^(unsuccessful|duplicate-customer)$ Nothing branches on the status code alone, 200 is what every answer arrives as. Stored values Parameter Source {external_id} {parsedBody.lead-id} {redirect_url} {parsedBody.return-url} from the post The ping’s lead-id is passed to the post as lead-id, so the post does not have to re-identify the person. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Creditportal (CZ) Advertiser Creditportal Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 0 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": 350 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "3-1", "type": "startNode", "position": { "x": -620, "y": 700 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "postVerify", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -420, "y": 0 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_created-date}", "fields": [ { "source": "{data_created-date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+{period} days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "d.m.Y" } ] }, { "fieldName": "{data_nin}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "(\\d{6})(\\d{4})", "output": "\\1/\\2" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": " " } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": " " } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": " " } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "maternity" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "pension - old-age" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "part-time" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] }, { "fieldName": "{data_employer_phone}", "fields": [ { "source": "{data_employer_phone}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "777777777" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "home owner" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "with parents" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "employee benefit" } ] }, { "fieldName": "{data_job_title}", "fields": [ { "source": "{data_job_title}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] }, { "fieldName": "{data_employer_address}", "fields": [ { "source": "{data_employer_address}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] }, { "fieldName": "{custom_gender}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "first_regex_match", "pattern": "", "output": "(?<=^\\d{2})\\d{2}" }, { "source": "{_1}", "operator": "is_greater_than", "value": "12", "value2": "", "modification": "replace", "pattern": "", "output": "F" }, { "source": "{_1}", "operator": "is_less_than", "value": "13", "value2": "", "modification": "replace", "pattern": "", "output": "M" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -150, "y": 0 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/cs/api", "timeout": 30, "format": "x-www-form-urlencoded+json-data", "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [], "body": [ { "key": "format", "value": "json" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.date", "value": "{data_created-date}" }, { "key": "data.name", "value": "{data_first_name}" }, { "key": "data.town", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.phone", "value": "{data_cell_phone}" }, { "key": "data.amount", "value": "{data_requested_amount}" }, { "key": "data.bankId", "value": "{data_bank_code}" }, { "key": "data.gender", "value": "{custom_gender}" }, { "key": "data.street", "value": "{data_street}" }, { "key": "data.birthId", "value": "{data_nin}" }, { "key": "data.command", "value": "checkFullLeadWithoutContact" }, { "key": "data.partner", "value": "{token}" }, { "key": "data.product", "value": "online" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.version", "value": "1.4" }, { "key": "data.chanelId", "value": "API" }, { "key": "data.expenses", "value": "{data_expenses}" }, { "key": "data.jobTitle", "value": "{data_job_title}" }, { "key": "data.citizenId", "value": "{data_identity_card_number}" }, { "key": "data.requestId", "value": "{eid}" }, { "key": "data.timestamp", "value": "toInt({timestamp})" }, { "key": "data.birthPlace", "value": "{data_city}" }, { "key": "data.homeStatus", "value": "{data_home_status}" }, { "key": "data.postalCode", "value": "{data_zip}" }, { "key": "data.bankAccount", "value": "{data_account_number}" }, { "key": "data.companyName", "value": "{data_employer}" }, { "key": "data.townContact", "value": "{data_contact_city}" }, { "key": "data.birthCountry", "value": "Česká republika" }, { "key": "data.companyPhone", "value": "{data_employer_phone}" }, { "key": "data.employedTime", "value": "{data_employed_time}" }, { "key": "data.incomeAmount", "value": "{data_monthly_income}" }, { "key": "data.incomeSource", "value": "{data_income_type}" }, { "key": "data.companyNumber", "value": "{data_company_number}" }, { "key": "data.contactPerson", "value": "nezadáno" }, { "key": "data.streetContact", "value": "{data_contact_street}" }, { "key": "data.employerAddress", "value": "{data_employer_address}" }, { "key": "data.contactPersonType", "value": "unclassifiable" }, { "key": "data.postalCodeContact", "value": "{data_contact_zip}" }, { "key": "data.contactPersonPhone", "value": "111111111" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": 120, "y": 100 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "Validation failed", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "Invalid parameter", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-5", "type": "endNode", "position": { "x": 390, "y": -70 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-6", "type": "endNode", "position": { "x": 390, "y": 100 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -420, "y": 350 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_created-date}", "fields": [ { "source": "{data_created-date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+{period} days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "d.m.Y" } ] }, { "fieldName": "{custom_birth_id}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "^(\\d{6})/?(\\d{3,4})$", "output": "\\1/\\2" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "maternity" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "pension - old-age" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "part-time" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] }, { "fieldName": "{data_employer_phone}", "fields": [ { "source": "{data_employer_phone}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "777777777" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "home owner" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "with parents" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "employee benefit" } ] }, { "fieldName": "{data_job_title}", "fields": [ { "source": "{data_job_title}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] }, { "fieldName": "{data_employer_address}", "fields": [ { "source": "{data_employer_address}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nezadáno" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -150, "y": 350 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/cs/api", "timeout": 30, "format": "x-www-form-urlencoded+json-data", "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [], "body": [ { "key": "format", "value": "json" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.date", "value": "{data_created-date}" }, { "key": "data.name", "value": "{data_first_name}" }, { "key": "data.town", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.phone", "value": "{data_cell_phone}" }, { "key": "data.amount", "value": "{data_requested_amount}" }, { "key": "data.bankId", "value": "{data_bank_code}" }, { "key": "data.gender", "value": "{data_nin}" }, { "key": "data.street", "value": "{data_street}" }, { "key": "data.birthId", "value": "{custom_birth_id}" }, { "key": "data.command", "value": "submitLead" }, { "key": "data.partner", "value": "{token}" }, { "key": "data.product", "value": "online" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.version", "value": "1.4" }, { "key": "data.chanelId", "value": "API" }, { "key": "data.expenses", "value": "{data_expenses}" }, { "key": "data.jobTitle", "value": "{data_job_title}" }, { "key": "data.citizenId", "value": "{data_identity_card_number}" }, { "key": "data.timestamp", "value": "toInt({timestamp})" }, { "key": "data.birthPlace", "value": "{data_city}" }, { "key": "data.homeStatus", "value": "{data_home_status}" }, { "key": "data.postalCode", "value": "{data_zip}" }, { "key": "data.bankAccount", "value": "{data_account_number}" }, { "key": "data.companyName", "value": "{data_employer}" }, { "key": "data.requestedId", "value": "{eid}" }, { "key": "data.townContact", "value": "{data_contact_city}" }, { "key": "data.birthCountry", "value": "Česká republika" }, { "key": "data.companyPhone", "value": "{data_employer_phone}" }, { "key": "data.employedTime", "value": "{data_employed_time}" }, { "key": "data.incomeAmount", "value": "{data_monthly_income}" }, { "key": "data.incomeSource", "value": "{data_income_type}" }, { "key": "data.companyNumber", "value": "{data_company_number}" }, { "key": "data.contactPerson", "value": "nezadáno" }, { "key": "data.streetContact", "value": "{data_contact_street}" }, { "key": "data.employerAddress", "value": "{data_employer_address}" }, { "key": "data.contactPersonType", "value": "unclassifiable" }, { "key": "data.postalcodeContact", "value": "{data_contact_zip}" }, { "key": "data.contactPersonPhone", "value": "111111111" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": 120, "y": 280 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{token_id}", "value": "{parsedBody.data.tokenId}" }, { "key": "{token_code}", "value": "{parsedBody.data.tokenCode}" }, { "key": "{external_id}", "value": "{parsedBody.data.loanNumber}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 390, "y": 280 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": 120, "y": 440 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "Validation failed", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "Invalid parameter", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 390, "y": 440 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "3-2", "type": "httpNode", "position": { "x": -350, "y": 700 }, "data": { "formData": { "active": true, "title": "Verify", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/cs/api", "timeout": 30, "format": "x-www-form-urlencoded+json-data", "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [], "body": [ { "key": "command", "value": "submitToken" }, { "key": "partner", "value": "{token}" }, { "key": "tokenId", "value": "{token_id}" }, { "key": "version", "value": "1.4" }, { "key": "timestamp", "value": "toInt({timestamp})" }, { "key": "tokenCode", "value": "{token_code}" }, { "key": "tokenValue", "value": "{code}" } ], "signature": null, "insecure": null } } }, { "id": "3-3", "type": "setNode", "position": { "x": -70, "y": 630 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.redirectUri}" } ] } } }, { "id": "3-5", "type": "endNode", "position": { "x": 220, "y": 630 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "3-4", "type": "modifyFieldNode", "position": { "x": -70, "y": 790 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.data.status}", "operator": "equals", "value": "incorrect", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.data.status}", "operator": "equals", "value": "expired", "value2": "", "modification": "replace", "pattern": "", "output": "Expired" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "3-6", "type": "endNode", "position": { "x": 220, "y": 790 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-3-1-3-2", "source": "3-1", "target": "3-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "(?:\"status\"\\s*:\\s*\"error\"|\"accepted\"\\s*:\\s*false)", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "ok", "output2": "" }, { "value": "{parsedBody.data.accepted}", "operator": "is_true", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "ok", "output2": "" }, { "value": "{parsedBody.data.accepted}", "operator": "is_true", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "(?:\"status\"\\s*:\\s*\"error\"|\"accepted\"\\s*:\\s*false)", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-3-2-3-3", "source": "3-2", "target": "3-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "ok", "output2": "" }, { "value": "{parsedBody.data.accepted}", "operator": "is_true", "output": "", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "ok", "output2": "" } ] } }, { "id": "edge-3-2-3-4", "source": "3-2", "target": "3-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "(?:\"status\"\\s*:\\s*\"error\"|\"accepted\"\\s*:\\s*false)", "output2": "" } ] } }, { "id": "edge-3-3-3-5", "source": "3-3", "target": "3-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-3-4-3-6", "source": "3-4", "target": "3-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details CreditPortal uses one endpoint for three independent flows: a prescore Ping, lead submission, and SMS verification. Every call is an HTTP POST to /cs/api; the operation is chosen by the command field. The live/legacy flow in the current blueprint is checkFullLeadWithoutContact → submitLead → submitToken. The newer advertiser note about sending an smsCode directly with submitLead is not activated because its rollout and exact contract are not proven by the current integration. What will be needed from advertiser Key Purpose endpoint Base API URL; the blueprint appends /cs/api. token Partner identifier sent as partner. sign_secret Shared secret used for the CreditPortal MD5 request signature. Flows Ping, command checkFullLeadWithoutContact. Sends the lead data and checks data.accepted. Post, command submitLead. On success stores the loan number and SMS token identifiers. Verify, command submitToken. Verifies the SMS code and returns redirectUri when accepted. These flows are independent Start paths; do not connect Ping directly to Post or Post directly to Verify in the integration canvas. Calls POST {endpoint}/cs/api Ping and Post use the JSON-in-form shape (format: x-www-form-urlencoded+json-data) with format=json plus data.* fields. The current blueprint dump also shows Verify in this format. CreditPortal signs requests as MD5 of the sent values joined by |, followed by | and the shared secret. The secret itself is never sent. The current blueprint dump has signature: null on Ping, Post and Verify even though the advertiser contract requires signing, so those nodes must be configured with the MD5-values-secret signature using sign_secret before production. Request fields Common lead fields — Ping and Post Field Value partner {token} version 1.4 timestamp toInt({timestamp}) ip {ip_address} date due date derived from the lead date + requested period, d.m.Y name, surname applicant name email, phone contact data birthId national ID with slash citizenId ID-card number gender derived helper in Ping; current Post preserves the production-proven raw-source behavior birthPlace current blueprint maps residential city; verify upstream semantics if a real birthplace field becomes available birthCountry Česká republika street, town, postalCode permanent address streetContact, townContact, contact postal code contact address amount {g_amount} / current requested amount; the latest blueprint sends it without an integration-level cap bankAccount, bankId account number and bank code incomeSource, incomeAmount, expenses finance data companyName, companyNumber, companyPhone, employerAddress, jobTitle, employedTime employment data product online chanelId API requestId / requestedId {send_id}-style source identifier; field spelling differs between Ping and Post The current payload intentionally preserves two production-proven asymmetries: Ping uses requestId and postalCodeContact; Post uses requestedId and postalcodeContact. Verify Field Value command submitToken partner {token} version 1.4 timestamp toInt({timestamp}) tokenId value stored from Post tokenCode value stored from Post tokenValue verification code entered by the client Transforms The due date is calculated as the lead date plus {g_period} days and formatted d.m.Y. National ID is normalised to the slash form for birthId. Income and housing labels are translated to the advertiser vocabulary. The current blueprint also fills several fields the API historically expected even when source data is empty; these are compatibility placeholders, not credentials. An older signed preflight used a 30000 amount cap, but the latest blueprint dump no longer contains that transform. This page follows the latest blueprint; if 30000 is still the commercial maximum, align the blueprint separately rather than documenting a cap that is not currently there. Outcomes Flow Recognised by Meaning Reject reason Ping HTTP 200, status: ok, data.accepted: true Advertiser wants the lead Ping HTTP 200, recognised status: error or data.accepted: false Business refusal Unspecified, or Invalid Data when message names validation Post HTTP 200, status: ok, data.accepted: true Lead accepted; SMS verification data returned Post HTTP 200, recognised error / accepted: false Business refusal Unspecified / Invalid Data Verify HTTP 200, status: ok, data.accepted: true, data.status: ok SMS verified Verify data.status: incorrect Wrong SMS code Invalid Data Verify data.status: expired SMS token expired Expired technical HTTP 5xx Advertiser failure technical error, not a business rejection Every reject node carries raw {body} in {reason_detail}. Branching Ping accepted: {status} equals 200 {parsedBody.status} equals ok {parsedBody.data.accepted} is true Post accepted uses the same three predicates. Verify accepted: {status} equals 200 {parsedBody.status} equals ok {parsedBody.data.accepted} is true {parsedBody.data.status} equals ok Unexpected/malformed HTTP-200 shapes should not be flattened into a generic rejection unless they match a documented business response. A real 5xx is left technical. Stored values Parameter Source {token_id} {parsedBody.data.tokenId} from Post {token_code} {parsedBody.data.tokenCode} from Post {external_id} {parsedBody.data.loanNumber} from Post {redirect_url} {parsedBody.data.redirectUri} from Verify Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Duofin (CZ) Advertiser Duofin Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -760, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -760, "y": 400 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -550, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{same_address}", "fields": [ { "source": "{data_different_contact_address}", "operator": "equals", "value": "true", "value2": "", "modification": "replace", "pattern": "", "output": "0" }, { "source": "{data_different_contact_address}", "operator": "equals", "value": "false", "value2": "", "modification": "replace", "pattern": "", "output": "1" } ] }, { "fieldName": "{data_employed_time}", "fields": [ { "source": "{data_employed_time}", "operator": "equals", "value": "3-month", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-year", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-2-year", "value2": "", "modification": "replace", "pattern": "", "output": "4" }, { "source": "{data_employed_time}", "operator": "equals", "value": "2-5-year", "value2": "", "modification": "replace", "pattern": "", "output": "5" }, { "source": "{data_employed_time}", "operator": "equals", "value": "5-year-plus", "value2": "", "modification": "replace", "pattern": "", "output": "8" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -310, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/fe/leadSignUp", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [ { "key": "zip", "value": "{data_zip}" }, { "key": "auth", "value": "{token}" }, { "key": "city", "value": "{data_city}" }, { "key": "email", "value": "{data_email}" }, { "key": "period", "value": "toInt({data_period})" }, { "key": "street", "value": "{data_street}" }, { "key": "employer", "value": "{data_employer}" }, { "key": "bank_code", "value": "{data_bank_code}" }, { "key": "job_title", "value": "{data_job_title}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "cell_phone", "value": "{data_cell_phone}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "ip_address", "value": "{ip_address}" }, { "key": "contact_zip", "value": "{data_contact_zip}" }, { "key": "home_status", "value": "{data_home_status}" }, { "key": "income_type", "value": "{data_income_type}" }, { "key": "birth_number", "value": "{data_nin}" }, { "key": "contact_city", "value": "{data_contact_city}" }, { "key": "house_number", "value": "{data_house_number}" }, { "key": "same_address", "value": "toBool({same_address})" }, { "key": "employed_time", "value": "toInt({data_employed_time})" }, { "key": "source_detail", "value": "{eid}" }, { "key": "company_number", "value": "{data_company_number_imported}" }, { "key": "contact_street", "value": "{data_contact_street}" }, { "key": "employer_phone", "value": "{data_employer_phone}" }, { "key": "monthly_income", "value": "toInt({data_monthly_income})" }, { "key": "employer_address", "value": "{data_employer_address}" }, { "key": "monthly_expenses", "value": "toInt({data_expenses})" }, { "key": "requested_amount", "value": "toFloat({data_requested_amount})" }, { "key": "bank_account_number", "value": "{data_account_number}" }, { "key": "contact_house_number", "value": "{data_contact_house_number}" }, { "key": "identity_card_number", "value": "{data_identity_card_number}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": -40, "y": -20 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.refno}" }, { "key": "{redirect_url}", "value": "{parsedBody.url}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 210, "y": -20 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": -40, "y": 140 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "DuoFinance status {parsedBody.status}" }, { "source": "{parsedBody.refno}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "DuoFinance status {parsedBody.status}, refno={parsedBody.refno}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 210, "y": 140 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -550, "y": 400 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "HOME_OWNER" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "CO_OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE_BENEFIT" } ] }, { "fieldName": "{data_period}", "fields": [ { "source": "{data_period}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "30" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -310, "y": 400 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/fe/leadFindPerson", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [ { "key": "zip", "value": "{data_zip}" }, { "key": "auth", "value": "{token}" }, { "key": "city", "value": "{data_city}" }, { "key": "period", "value": "toInt({data_period})" }, { "key": "street", "value": "{data_street}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "ip_address", "value": "{ip_address}" }, { "key": "home_status", "value": "{data_home_status}" }, { "key": "birth_number", "value": "{data_nin}" }, { "key": "house_number", "value": "{data_house_number}" }, { "key": "source_detail", "value": "{eid}" }, { "key": "requested_amount", "value": "toFloat({data_requested_amount})" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "endNode", "position": { "x": -40, "y": 340 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -40, "y": 500 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "DuoFinance status {parsedBody.status}" }, { "source": "{parsedBody.refno}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "DuoFinance status {parsedBody.status}, refno={parsedBody.refno}" } ] } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 210, "y": 500 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "Accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "404", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "404", "output2": "" }, { "value": "{parsedBody.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "Rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "Accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "404", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "404", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "Rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" } ] } }, { "id": "edge-2-5-2-6", "source": "2-5", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Everything travels in the query string on GET requests, and the status codes are inverted relative to every other integration in this library: HTTP Meaning 404 The advertiser wants the lead 200 The advertiser is not interested 500 Mixed: sometimes a real failure, sometimes a validation message 404 means “person not found”, which is exactly the answer that makes a lead worth having. An integration that treats 404 as a failure and 200 as a success sells nothing and reports every good lead as an error. What will be needed from advertiser Key Purpose endpoint Base API URL. token Value for the auth query parameter. Flows Ping, GET /fe/leadFindPerson. Identifying fields only. 404 means proceed. Post, GET /fe/leadSignUp. Full payload. 404 with a url means accepted. Calls GET {endpoint}/fe/leadFindPerson?auth={token}&… GET {endpoint}/fe/leadSignUp?auth={token}&… Auth is the auth query parameter. There are no headers and no body. Request fields All as query parameters. Ping Field Required Value auth yes {token} first_name yes {g_name_first} last_name yes {g_name_last} birth_number yes {g_id_national_number} street yes {g_address_street} house_number yes {g_address_street_number} city yes {g_address_city} zip yes {g_address_zip} home_status yes {g_home_type}, see enums requested_amount yes toFloat({g_amount}) period yes toInt({g_period}) ip_address yes {ip_address} source_detail yes {send_id} Post Everything above, plus: Field Required Value email yes {g_email} cell_phone yes {g_phone} identity_card_number yes {g_id_card_number} income_type yes {g_fin_type}, see enums monthly_income yes toInt({g_fin_income}) monthly_expenses yes toInt({g_fin_expenses}) employer no {g_employer_name} employer_phone no {g_employer_phone} employer_address no {g_employer_address} job_title no {g_employ_position} employed_time no {g_employ_time}, see enums company_number self-employed {g_company_registration} bank_account_number yes {g_bank_account_number} bank_code yes {g_bank_account_code} contact_street no {g_address_contact_street} contact_zip no {g_address_contact_zip} contact_city no {g_address_contact_city} same_address yes toBool(...), inverse of {g_address_contact_status} marital_status no {g_marital_status}, see enums same_address is inverted relative to a “contact address differs” checkbox. Numeric fields are typed. Convert inline with toInt(...) and toFloat(...) in the HTTP node, one conversion, never nested. Enums income_type: EMPLOYED, SELF_EMPLOYED, MATERNITY_LEAVE, PENSION, UNEMPLOYED, OTHER. home_status: HOME_OWNER, TENANT, DORMITORY, HOSTEL, MINISTRY, EMPLOYEE_BENEFIT, CO_OWNED. marital_status: SINGLE, MARRIED, PARTNERSHIP, DIVORCED, WIDOWED, SEPARATED. employed_time is a bucket count: 1 under three months, 3 under a year, 4 one to two years, 5 two to five years, 8 over five years. Where the form’s bucket falls between two of the advertiser’s, choose the one that presents the lead as qualifying. Outcomes The body carries its own status field and it does not agree with the HTTP status code. Neither one alone is reliable at the post: the signal that the lead was taken is the presence of url. Recognised by HTTP Meaning Reject reason Frequency status: 404 404 Person not known, proceed , common url present 404 Accepted , common status: 200 200 Not interested, no reason given Unspecified common , 500 Internal error , (technical) rare The vocabulary is this small. There is no reason code and no message beyond Person not found, so every refusal is Unspecified. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, proceed: {status} equals 404 {parsedBody.status} equals 404 The ping also returns 404 with refno and url already filled in for a person the advertiser recognises. Both are still “wanted”; the post is what records the lead. Ping, not interested: {status} equals 200 {parsedBody.status} equals 200 Post, accepted: {status} equals 404 {parsedBody.status} equals 404 {parsedBody.url} is not empty Post, refused: {status} equals 200 {parsedBody.status} equals 200 500 gets a branch only for the validation cases, and only because the body names a field: {status} equals 500 {body} regex match Kontrolni cifra|Invalid email address leadgenia: disabled and the database errors get no branch. They Dead End, which is what makes them visible. Stored values Parameter Source {external_id} {parsedBody.refno} {redirect_url} {parsedBody.url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Ferratum (CZ) Advertiser Ferratum Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -341.23002826097, "y": -23.971689380365 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "setNode", "position": { "x": -283.46312459377, "y": -222.41073759441 }, "data": { "formData": { "active": true, "title": "Auth credentials", "subtitle": "", "fields": [ { "key": "{auth0}", "value": "{sign_keyid}:{token}" } ] } } }, { "id": "1-3", "type": "modifyFieldNode", "position": { "x": -152.70369826911, "y": -132.96895032007 }, "data": { "formData": { "active": true, "title": "Auth header", "subtitle": "", "data": [ { "fieldName": "{auth}", "fields": [ { "source": "{auth0}", "operator": "always", "value": "", "value2": "", "modification": "to_base64", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-4", "type": "httpNode", "position": { "x": -91.161714805027, "y": 32.295557575104 }, "data": { "formData": { "active": true, "title": "Auth", "subtitle": "", "method": "POST", "endpoint": "{endpoint_auth}oauth/token", "timeout": 30, "format": "application/x-www-form-urlencoded", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/x-www-form-urlencoded" }, { "key": "Authorization", "value": "Basic {auth}" } ], "query": [], "body": [ { "key": "grant_type", "value": "client_credentials" } ], "signature": null, "insecure": null } } }, { "id": "1-5", "type": "setNode", "position": { "x": 17, "y": -100 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{access_token}", "value": "{parsedBody.access_token}" } ] } } }, { "id": "1-7", "type": "modifyFieldNode", "position": { "x": 148.5, "y": 30.5 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{birth_date}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "cz_nin_to_birthdate", "pattern": "", "output": "" } ] }, { "fieldName": "{data_cell_phone}", "fields": [ { "source": "{data_cell_phone}", "operator": "always", "value": "", "value2": "", "modification": "prefix", "pattern": "", "output": "+420" } ] } ] } } }, { "id": "1-9", "type": "httpNode", "position": { "x": 254.00375602962, "y": -126.27723037408 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}api/v1/loan-applications", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Host", "value": "{custom_host}" }, { "key": "Digest", "value": "{digest}" }, { "key": "Signature", "value": "{signature}" }, { "key": "X-Request-Id", "value": "{step_run_id}" }, { "key": "Authorization", "value": "Bearer {access_token}" } ], "query": [], "body": [ { "key": "country", "value": "CZ" }, { "key": "language", "value": "cs" }, { "key": "debtors.0.role", "value": "1" }, { "key": "debtors.0.type", "value": "NATURAL_PERSON" }, { "key": "applyForLoan.loanType", "value": "CREDIT_LIMIT" }, { "key": "applyForLoan.term.term", "value": "6" }, { "key": "applyForLoan.amount.amount", "value": "{data_requested_amount}" }, { "key": "applyForLoan.term.termUnit", "value": "MONTH" }, { "key": "applyForLoan.partnerPurpose", "value": "OTHER" }, { "key": "applyForLoan.amount.currency", "value": "CZK" }, { "key": "debtors.0.person.formattedName", "value": "{data_first_name} {data_last_name}" }, { "key": "debtors.0.person.emails.0.value", "value": "{data_email}" }, { "key": "debtors.0.person.addresses.0.type", "value": "RESIDENCE" }, { "key": "debtors.0.person.emails.0.primary", "value": "true" }, { "key": "debtors.0.person.identities.0.type", "value": "SSN" }, { "key": "debtors.0.person.identities.0.value", "value": "{data_nin}" }, { "key": "debtors.0.person.addresses.0.country", "value": "CZ" }, { "key": "debtors.0.person.addresses.0.primary", "value": "true" }, { "key": "debtors.0.person.phoneNumbers.0.type", "value": "MOBILE" }, { "key": "debtors.0.person.identities.0.primary", "value": "true" }, { "key": "debtors.0.person.phoneNumbers.0.value", "value": "{data_cell_phone}" }, { "key": "applyForLoan.preferences.affiliateMode", "value": "HAND_OVER" }, { "key": "applyForLoan.preferences.exactMatchOnly", "value": "false" }, { "key": "debtors.0.person.phoneNumbers.0.primary", "value": "true" }, { "key": "applyForLoan.preferences.contractRequired", "value": "false" }, { "key": "applyForLoan.preferences.oneOfferRequired", "value": "true" }, { "key": "debtors.0.person.naturalPerson.birth.date", "value": "{birth_date}" }, { "key": "debtors.0.person.addresses.0.components.0.type", "value": "CITY" }, { "key": "debtors.0.person.addresses.0.components.1.type", "value": "ZIP_CODE" }, { "key": "debtors.0.person.addresses.0.components.2.type", "value": "ADDRESS_LINE_1" }, { "key": "debtors.0.person.naturalPerson.names.0.primary", "value": "true" }, { "key": "debtors.0.person.addresses.0.components.0.value", "value": "{data_city}" }, { "key": "debtors.0.person.addresses.0.components.1.value", "value": "{data_zip}" }, { "key": "debtors.0.person.addresses.0.components.2.value", "value": "{data_street}" }, { "key": "debtors.0.person.naturalPerson.names.0.lastName", "value": "{data_last_name}" }, { "key": "debtors.0.person.naturalPerson.names.0.firstName", "value": "{data_first_name}" }, { "key": "debtors.0.person.naturalPerson.employments.0.primary", "value": "true" }, { "key": "debtors.0.person.naturalPerson.employments.0.partnerType", "value": "{data_income_type}" }, { "key": "debtors.0.person.naturalPerson.employments.0.employer.name", "value": "{data_employer}" }, { "key": "debtors.0.person.naturalPerson.financialData.incomes.0.key", "value": "GROSS_INCOME" }, { "key": "debtors.0.person.naturalPerson.financialData.expenses.0.key", "value": "LIVING_COSTS" }, { "key": "debtors.0.person.naturalPerson.financialData.incomes.0.period", "value": "MONTH" }, { "key": "debtors.0.person.naturalPerson.financialData.expenses.0.period", "value": "MONTH" }, { "key": "debtors.0.person.naturalPerson.otherFacts.partnerMaritalStatus", "value": "SINGLE" }, { "key": "debtors.0.person.naturalPerson.financialData.incomes.0.value.amount", "value": "{data_monthly_income}" }, { "key": "debtors.0.person.naturalPerson.financialData.expenses.0.value.amount", "value": "{data_expenses}" }, { "key": "debtors.0.person.naturalPerson.financialData.incomes.0.value.currency", "value": "CZK" }, { "key": "debtors.0.person.naturalPerson.financialData.expenses.0.value.currency", "value": "CZK" }, { "key": "debtors.0.person.naturalPerson.financialData.otherLoans.0.amount.amount", "value": "0" }, { "key": "debtors.0.person.naturalPerson.financialData.otherLoans.0.amount.currency", "value": "CZK" } ], "signature": { "type": "digest_keyid_hmac", "sha": "256", "delimiter": "&" }, "insecure": null } } }, { "id": "1-10", "type": "setNode", "position": { "x": 405.20498262388, "y": -13.25146146664 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.applicationId}" } ] } } }, { "id": "1-12", "type": "webhookNode", "position": { "x": 513.41897676778, "y": 65.756733488738 }, "data": { "formData": { "active": true, "title": "Status webhook", "subtitle": "", "wait": true, "timeout": 20, "token": "1" } } }, { "id": "1-14", "type": "httpNode", "position": { "x": 728.00900866109, "y": -99.270543507305 }, "data": { "formData": { "active": true, "title": "Offer", "subtitle": "", "method": "GET", "endpoint": "{endpoint}api/v1/applications/{external_id}/offers", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Host", "value": "{custom_host}" }, { "key": "Signature", "value": "{signature}" }, { "key": "Timestamp", "value": "{timestamp}" }, { "key": "X-Request-Id", "value": "{step_run_id}" }, { "key": "Authorization", "value": "Bearer {access_token}" } ], "query": [], "body": [], "signature": { "type": "digest_keyid_hmac", "sha": "256", "delimiter": "&" }, "insecure": null } } }, { "id": "1-15", "type": "waitNode", "position": { "x": 492.33880260633, "y": 258.16023970723 }, "data": { "formData": { "active": true, "title": "Wait 1s", "subtitle": "", "type": "delay", "delayValue": 1, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-16", "type": "httpNode", "position": { "x": 442.26481761024, "y": -165.75462475225 }, "data": { "formData": { "active": true, "title": "Status", "subtitle": "", "method": "GET", "endpoint": "{endpoint}api/v1/applications/{external_id}/status", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Host", "value": "{custom_host}" }, { "key": "Signature", "value": "{signature}" }, { "key": "Timestamp", "value": "{timestamp}" }, { "key": "X-Request-Id", "value": "{step_run_id}" }, { "key": "Authorization", "value": "Bearer {access_token}" } ], "query": [], "body": [], "signature": { "type": "digest_keyid_hmac", "sha": "256", "delimiter": "&" }, "insecure": null } } }, { "id": "1-17", "type": "setNode", "position": { "x": 929.85193259436, "y": 32.551911181055 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.offers.0.offerUrl}" }, { "key": "{external_id}", "value": "{parsedBody.offers.0.offerId}" } ] } } }, { "id": "1-18", "type": "waitNode", "position": { "x": 752.07850487013, "y": 172.91327217542 }, "data": { "formData": { "active": true, "title": "Wait 2s", "subtitle": "", "type": "delay", "delayValue": 2, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-19", "type": "breakerNode", "position": { "x": 617.33848069845, "y": 270.05632074515 }, "data": { "formData": { "active": true, "title": "Breaker 3x", "subtitle": "", "maxRepetition": "3" } } }, { "id": "1-21", "type": "endNode", "position": { "x": 1092.1663804927, "y": -178.77534002409 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-22", "type": "breakerNode", "position": { "x": 882.13768907333, "y": 218.54131718867 }, "data": { "formData": { "active": true, "title": "Breaker 2x", "subtitle": "", "maxRepetition": "2" } } }, { "id": "1-6", "type": "modifyFieldNode", "position": { "x": 17, "y": 220 }, "data": { "formData": { "active": true, "title": "Reject reason · Auth", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.access_token}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "auth failed, http {status}" }, { "source": "{parsedBody.error_description}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.error_description}" } ] } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": 195.03505083052, "y": 182.76288122891 }, "data": { "formData": { "active": true, "title": "Rejected · Auth", "subtitle": "", "success": "failed" } } }, { "id": "1-11", "type": "modifyFieldNode", "position": { "x": 280.25376185867, "y": 290.89759318929 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.applicationId}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{parsedBody.errors.0.code}", "operator": "contains", "value": "LENDING_0115", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.errors.0.code}", "operator": "contains", "value": "LENDING_0327", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.errors.0.code}", "operator": "contains", "value": "LENDING_0328", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.errors.0.code}", "operator": "contains", "value": "LENDING_0329", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.errors.0.code}", "operator": "contains", "value": "LENDING_0330", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.errors.0.code}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.errors.0.code}: {parsedBody.errors.0.detail}" } ] } ] } } }, { "id": "1-13", "type": "endNode", "position": { "x": 572.4123729237, "y": 381.9216612964 }, "data": { "formData": { "active": true, "title": "Rejected · Post", "subtitle": "", "success": "failed" } } }, { "id": "1-20", "type": "modifyFieldNode", "position": { "x": 600, "y": -340 }, "data": { "formData": { "active": true, "title": "Reject reason · Status", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.applicationStatus}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.closingType}", "operator": "equals", "value": "EXPIRED", "value2": "", "modification": "replace", "pattern": "", "output": "Expired" }, { "source": "{parsedBody.closingType}", "operator": "equals", "value": "CANCELLED_BY_USER", "value2": "", "modification": "replace", "pattern": "", "output": "Cancelled by Customer" }, { "source": "{parsedBody.closingType}", "operator": "equals", "value": "CANCELLED_BY_PARTNER", "value2": "", "modification": "replace", "pattern": "", "output": "Cancelled by Advertiser" }, { "source": "{parsedBody.closingType}", "operator": "equals", "value": "CANCELLED_BY_SYSTEM", "value2": "", "modification": "replace", "pattern": "", "output": "Cancelled by Advertiser" }, { "source": "{parsedBody.closingType}", "operator": "equals", "value": "DENIED_BY_SCORING", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_001", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_002", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_003", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_004", "value2": "", "modification": "replace", "pattern": "", "output": "Fraud" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_005", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_007", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_008", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_010", "value2": "", "modification": "replace", "pattern": "", "output": "Low Income" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_013", "value2": "", "modification": "replace", "pattern": "", "output": "Verification Failed" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_020", "value2": "", "modification": "replace", "pattern": "", "output": "Low Income" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_021", "value2": "", "modification": "replace", "pattern": "", "output": "Too Much Debt" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_023", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_025", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_026", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_103", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "contains", "value": "LENDING_DENY_999", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.applicationStatus}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.applicationStatus} / {parsedBody.closingType}" }, { "source": "{parsedBody.closingReasons.0.code}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.closingType} / {parsedBody.closingReasons.0.code}: {parsedBody.closingReasons.0.description}" } ] } ] } } }, { "id": "1-23", "type": "endNode", "position": { "x": 860, "y": -340 }, "data": { "formData": { "active": true, "title": "Rejected · Status", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-5", "source": "1-4", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.access_token}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "auth failed", "subtitle": "", "conditions": [ { "value": "{parsedBody.access_token}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-9", "source": "1-7", "target": "1-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-9-1-10", "source": "1-9", "target": "1-10", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{parsedBody.applicationId}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-9-1-11", "source": "1-9", "target": "1-11", "type": "customEdge", "data": { "active": true, "title": "no applicationId", "subtitle": "", "conditions": [ { "value": "{parsedBody.applicationId}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-10-1-12", "source": "1-10", "target": "1-12", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-19-1-12", "source": "1-19", "target": "1-12", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{operationStatus}", "operator": "not_equals", "output": "COMPLETED", "output2": "" }, { "value": "{actionType}", "operator": "not_equals", "output": "status-update", "output2": "" } ] } }, { "id": "edge-1-16-1-12", "source": "1-16", "target": "1-12", "type": "customEdge", "data": { "active": true, "title": "not DEN|CAN", "subtitle": "", "conditions": [ { "value": "{parsedBody.applicationStatus}", "operator": "regex_not_match", "output": "DEN|CAN", "output2": "" } ] } }, { "id": "edge-1-12-1-14", "source": "1-12", "target": "1-14", "type": "customEdge", "data": { "active": true, "title": "offers-ready", "subtitle": "", "conditions": [ { "value": "{operationStatus}", "operator": "equals", "output": "COMPLETED", "output2": "" }, { "value": "{actionType}", "operator": "equals", "output": "offers-ready", "output2": "" } ] } }, { "id": "edge-1-12-1-15", "source": "1-12", "target": "1-15", "type": "customEdge", "data": { "active": true, "title": "Not status-update", "subtitle": "", "conditions": [ { "value": "{operationStatus}", "operator": "not_equals", "output": "COMPLETED", "output2": "" }, { "value": "{actionType}", "operator": "not_equals", "output": "status-update", "output2": "" } ] } }, { "id": "edge-1-12-1-16", "source": "1-12", "target": "1-16", "type": "customEdge", "data": { "active": true, "title": "status-update", "subtitle": "", "conditions": [ { "value": "{operationStatus}", "operator": "equals", "output": "COMPLETED", "output2": "" }, { "value": "{actionType}", "operator": "equals", "output": "status-update", "output2": "" } ] } }, { "id": "edge-1-22-1-14", "source": "1-22", "target": "1-14", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-14-1-17", "source": "1-14", "target": "1-17", "type": "customEdge", "data": { "active": true, "title": "APPROVED", "subtitle": "", "conditions": [ { "value": "{parsedBody.offers.0.offerUrl}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-14-1-18", "source": "1-14", "target": "1-18", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.offers.0.offerUrl}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-15-1-19", "source": "1-15", "target": "1-19", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-16-1-20", "source": "1-16", "target": "1-20", "type": "customEdge", "data": { "active": true, "title": "DEN|CAN", "subtitle": "", "conditions": [ { "value": "{parsedBody.applicationStatus}", "operator": "regex_match", "output": "DEN|CAN", "output2": "" } ] } }, { "id": "edge-1-17-1-21", "source": "1-17", "target": "1-21", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-18-1-22", "source": "1-18", "target": "1-22", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-11-1-13", "source": "1-11", "target": "1-13", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-20-1-23", "source": "1-20", "target": "1-23", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details OAuth2 for a bearer token, a signed request body on top of it, an asynchronous decision delivered by webhook, and a separate call to fetch the offer once it exists. Four things have to go right in order: authenticate, submit, wait for the decision, fetch the offer. Each is a separate step and each can fail on its own. What will be needed from advertiser Key Purpose endpoint Base API URL for application, status and offer calls. token OAuth client secret. endpoint_auth Base URL for OAuth authentication. sign_keyid OAuth client ID and signing key ID. sign_secret HMAC signing secret. custom_host Host value used in signed requests. Flows Post, as one flow: Auth -> Post -> webhook (offers-ready | status-update) -> Offer -> Success | | +-- timeout -> Wait -> Breaker ---------+ | +-- status-update -> Status -> DENIED|CANCELLED -> Rejected Authentication runs once. The token stays valid for everything that follows, so a second Auth node before each request is duplication rather than safety. Calls Auth POST {endpoint_auth}oauth/token Authorization: Basic base64({sign_keyid}:{token}) Content-Type: application/x-www-form-urlencoded format: application/x-www-form-urlencoded grant_type=client_credentials The client ID and secret are the two halves of Basic auth. Build the header at run time from {sign_keyid} and {token} rather than storing an encoded blob. Post, Status and Offer POST {endpoint}api/v1/loan-applications GET {endpoint}api/v1/applications/{external_id}/status GET {endpoint}api/v1/applications/{external_id}/offers Authorization: Bearer {custom_access_token} Host: {custom_host} Digest: {digest} Signature: {signature} X-Request-Id: {step_run_id} Content-Type: application/json format: application/json Signing uses the digest_keyid_hmac algorithm with SHA-256 and & as the delimiter. The node computes {digest} and {signature}; the secret itself lives in sign_secret and never travels. sign_keyid is the public key identifier the advertiser uses to pick which secret to verify against, which is why it also serves as the OAuth client ID. Host has to be set explicitly because the signature covers it. Request fields Dotted paths, deeply nested, and the applicant sits inside a debtors array. Every field under it is prefixed debtors.0.. Field Required Value country yes CZ language yes cs debtors.0.role yes 1 debtors.0.type yes NATURAL_PERSON debtors.0.person.formattedName yes {g_name_first} {g_name_last} debtors.0.person.naturalPerson.names.0.firstName yes {g_name_first} debtors.0.person.naturalPerson.names.0.lastName yes {g_name_last} debtors.0.person.naturalPerson.names.0.primary yes true debtors.0.person.naturalPerson.birth.date yes {g_birth_date}, or derived, see below debtors.0.person.identities.0.type yes SSN debtors.0.person.identities.0.value yes {g_id_national_number} debtors.0.person.identities.0.primary yes true debtors.0.person.emails.0.value yes {g_email} debtors.0.person.emails.0.primary yes true debtors.0.person.phoneNumbers.0.type yes MOBILE debtors.0.person.phoneNumbers.0.value yes {g_phone} with +420 debtors.0.person.phoneNumbers.0.primary yes true debtors.0.person.addresses.0.type yes RESIDENCE debtors.0.person.addresses.0.country yes CZ debtors.0.person.addresses.0.primary yes true debtors.0.person.addresses.0.components.0 yes type: CITY, value: {g_address_city} debtors.0.person.addresses.0.components.1 yes type: ZIP_CODE, value: {g_address_zip} debtors.0.person.addresses.0.components.2 yes type: ADDRESS_LINE_1, value: {g_address_street} ...employments.0.partnerType yes {g_fin_type}, see enums ...employments.0.employer.name yes {g_employer_name} ...employments.0.primary yes true ...financialData.incomes.0.key yes GROSS_INCOME ...financialData.incomes.0.value.amount yes {g_fin_income} ...financialData.incomes.0.value.currency yes CZK ...financialData.incomes.0.period yes MONTH ...financialData.expenses.0.key yes LIVING_COSTS ...financialData.expenses.0.value.amount yes {g_fin_expenses} ...financialData.otherLoans.0.amount.amount yes {g_fin_expenses_credit} ...otherFacts.partnerMaritalStatus yes {g_marital_status}, see enums applyForLoan.loanType yes CREDIT_LIMIT applyForLoan.amount.amount yes {g_amount} applyForLoan.amount.currency yes CZK applyForLoan.term.term yes {g_period} applyForLoan.term.termUnit yes MONTH applyForLoan.partnerPurpose yes {g_purpose} applyForLoan.preferences.affiliateMode yes HAND_OVER applyForLoan.preferences.oneOfferRequired yes true applyForLoan.preferences.exactMatchOnly yes false applyForLoan.preferences.contractRequired yes false Date of birth comes from {g_birth_date} where the form collects it. Where it does not, derive it from the national ID with the built-in conversion rather than a hand-written regex: {custom_birth_date} source {g_id_national_number} always cz_nin_to_birthdate Phone numbers need the +420 prefix. Add it with the prefix modification. preferences.oneOfferRequired: true and affiliateMode: HAND_OVER are what make the flow usable: one offer is produced and the applicant is handed over to Ferratum to complete it. Enums partnerType on employment, partnerMaritalStatus and partnerPurpose all take Ferratum’s own vocabularies. They are agreed per partner rather than published, so take them from the current contract rather than assuming. The webhook Ferratum does not answer synchronously. The application returns an applicationId and the decision arrives later on the callback endpoint, carrying two fields: actionType With operationStatus: COMPLETED What to do offers-ready The offer exists Fetch it from the offers endpoint status-update The application changed state Fetch the status and read it A webhook that times out is not a rejection. Loop back through a Wait and a Breaker and ask the status endpoint directly. Both Breakers need their counts in their titles, and the synchronous limit applies for the whole time the applicant is on a loading screen. Outcomes The application call answers with an applicationId when it was accepted, and with an errors array when it was not. The decision itself arrives later, in applicationStatus and closingType from the status endpoint. Recognised by Meaning Reject reason Frequency applicationId present Application accepted, wait for the offer common offers.0.offerUrl present Offer ready, this is the conversion occasional applicationStatus not matching `DEN CAN` Still running errors.0.code: LENDING_0115 Payload refused Invalid Data occasional errors.0.code: LENDING_0327 to LENDING_0330 Payload refused Invalid Data occasional closingType: DENIED_BY_SCORING Refused by scoring Poor Credit occasional closingType: EXPIRED Offer never opened Expired occasional closingType: CANCELLED_BY_USER The applicant walked away Cancelled by Customer occasional closingType: CANCELLED_BY_PARTNER Ferratum cancelled it Cancelled by Advertiser rare closingType: CANCELLED_BY_SYSTEM Cancelled automatically Cancelled by Advertiser rare closingReasons.0.code: LENDING_DENY_001 Applicant underage Age occasional LENDING_DENY_002 Applicant over the age limit Age occasional LENDING_DENY_003 Too high risk Poor Credit common LENDING_DENY_004 Fraud suspected Fraud rare LENDING_DENY_005 Employment history too short Not Eligible occasional LENDING_DENY_008 Existing loan Existing Customer occasional LENDING_DENY_010 Monthly income too low Low Income occasional LENDING_DENY_013 Identification failed Verification Failed occasional LENDING_DENY_021 Affordability check Too Much Debt occasional LENDING_DENY_023 Credit rating too low Poor Credit common LENDING_DENY_025 Internal system error technical LENDING_DENY_026 Third-party error technical LENDING_DENY_103 Another offer already taken Existing Customer occasional LENDING_DENY_999 Refused, no reason given Unspecified occasional LENDING_DENY_025 and _026 are Ferratum’s own failures wearing a rejection code. They are not the lead’s fault and should not be reported as a rejection reason. Leave them uncovered rather than mapping them. An Auth call that returns no access_token is a broken integration, not a rejected lead. It gets its own End node and no reject reason. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Auth succeeded: {parsedBody.access_token} is not empty Application accepted: {parsedBody.applicationId} is not empty Webhook, offer ready: {operationStatus} equals COMPLETED {actionType} equals offers-ready Webhook, status changed: {operationStatus} equals COMPLETED {actionType} equals status-update Status, terminal rejection: {parsedBody.applicationStatus} regex match DEN|CAN Status, still running, back to the webhook: {parsedBody.applicationStatus} regex not match DEN|CAN Offer ready: {parsedBody.offers.0.offerUrl} is not empty The offers array needs its index. {parsedBody.offers.offerUrl} resolves to literal text, which is never empty, so the branch fires on every response including the ones with no offer at all. Stored values Parameter Source {custom_access_token} {parsedBody.access_token} from Auth {external_id} {parsedBody.applicationId} from the application, then {parsedBody.offers.0.offerId} once the offer exists {redirect_url} {parsedBody.offers.0.offerUrl} The application ID identifies the request; the offer ID identifies what was sold. Overwrite {external_id} with the offer ID at the end so the report reconciles against what Ferratum actually issued. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Flexifin (CZ) Advertiser Flexifin Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -560, "y": 360 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -560, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -360, "y": 360 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "HOME_OWNER" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "CO_OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE_BENEFIT" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -140, "y": 360 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1/leads/check", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [], "body": [ { "key": "code", "value": "{partner_id}" }, { "key": "token", "value": "{token}" }, { "key": "sourceDetail", "value": "{username}" }, { "key": "residenceAddress.zip", "value": "{data_zip}" }, { "key": "personalInfo.lastName", "value": "{data_last_name}" }, { "key": "residenceAddress.city", "value": "{data_city}" }, { "key": "personalInfo.firstName", "value": "{data_first_name}" }, { "key": "residenceAddress.street", "value": "{data_street}" }, { "key": "personalInfo.birthNumber", "value": "{data_nin}" }, { "key": "residenceAddress.homeStatus", "value": "{data_home_status}" }, { "key": "residenceAddress.houseNumber", "value": "{data_house_number}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "endNode", "position": { "x": 320, "y": 300 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -360, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_different_contact_address}", "fields": [ { "source": "{data_different_contact_address}", "operator": "equals", "value": "true", "value2": "", "modification": "replace", "pattern": "", "output": "0" }, { "source": "{data_different_contact_address}", "operator": "equals", "value": "false", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_different_contact_address}", "operator": "always", "value": "", "value2": "", "modification": "to_bool", "pattern": "", "output": "" } ] }, { "fieldName": "{data_cell_phone}", "fields": [ { "source": "{data_cell_phone}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "^\\s*(?:(?:\\+?420|00420)[\\s().-]*)?(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)\\s*$", "output": "+420$1$2$3$4$5$6$7$8$9" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_employer_phone}", "fields": [ { "source": "{data_employer_phone}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "^\\s*(?:(?:\\+?420|00420)[\\s().-]*)?(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)[\\s().-]*(\\d)\\s*$", "output": "+420$1$2$3$4$5$6$7$8$9" } ] }, { "fieldName": "{data_employed_time}", "fields": [ { "source": "{data_employed_time}", "operator": "equals", "value": "3-month", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-year", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-2-year", "value2": "", "modification": "replace", "pattern": "", "output": "4" }, { "source": "{data_employed_time}", "operator": "equals", "value": "2-5-year", "value2": "", "modification": "replace", "pattern": "", "output": "5" }, { "source": "{data_employed_time}", "operator": "equals", "value": "5-year-plus", "value2": "", "modification": "replace", "pattern": "", "output": "8" }, { "source": "{data_employed_time}", "operator": "always", "value": "", "value2": "", "modification": "to_int", "pattern": "", "output": "" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -140, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1/leads/signup", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [], "query": [], "body": [ { "key": "code", "value": "{partner_id}" }, { "key": "token", "value": "{token}" }, { "key": "period", "value": "toInt({data_period})" }, { "key": "product", "value": "loan" }, { "key": "ipAddress", "value": "{ip_address}" }, { "key": "sameAddress", "value": "{data_different_contact_address}" }, { "key": "sourceDetail", "value": "{username}" }, { "key": "requestedAmount", "value": "toInt({data_requested_amount})" }, { "key": "bankData.bankCode", "value": "{data_bank_code}" }, { "key": "contactAddress.zip", "value": "{data_contact_zip}" }, { "key": "personalInfo.email", "value": "{data_email}" }, { "key": "contactAddress.city", "value": "{data_contact_city}" }, { "key": "residenceAddress.zip", "value": "{data_zip}" }, { "key": "contactAddress.street", "value": "{data_contact_street}" }, { "key": "employerData.employer", "value": "{data_employer}" }, { "key": "employerData.jobTitle", "value": "{data_job_title}" }, { "key": "personalInfo.lastName", "value": "{data_last_name}" }, { "key": "residenceAddress.city", "value": "{data_city}" }, { "key": "personalInfo.cellPhone", "value": "{data_cell_phone}" }, { "key": "personalInfo.firstName", "value": "{data_first_name}" }, { "key": "personalInfo.incomeType", "value": "{data_income_type}" }, { "key": "residenceAddress.street", "value": "{data_street}" }, { "key": "incomeData.monthlyIncome", "value": "toInt({data_monthly_income})" }, { "key": "personalInfo.birthNumber", "value": "{data_nin}" }, { "key": "employerData.employedTime", "value": "{data_employed_time}" }, { "key": "bankData.bankAccountNumber", "value": "{data_account_number}" }, { "key": "contactAddress.houseNumber", "value": "{data_contact_house_number}" }, { "key": "employerData.employerPhone", "value": "{data_employer_phone}" }, { "key": "incomeData.monthlyExpenses", "value": "toInt({data_expenses})" }, { "key": "residenceAddress.homeStatus", "value": "{data_home_status}" }, { "key": "residenceAddress.houseNumber", "value": "{data_house_number}" }, { "key": "personalInfo.identityCardNumber", "value": "{data_identity_card_number}" }, { "key": "employerData.employerAddress.city", "value": "{data_employer_address}" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": 100, "y": -40 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.refNo}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 320, "y": -40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 100, "y": 440 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" }, { "source": "{parsedBody.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.message}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 320, "y": 440 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": 100, "y": 120 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" }, { "source": "{parsedBody.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.message}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 320, "y": 120 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.data.status}", "operator": "equals", "output": "Accepted", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.data.status}", "operator": "equals", "output": "Rejected", "output2": "" } ] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.data.status}", "operator": "equals", "output": "Accepted", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.data.status}", "operator": "equals", "output": "Rejected", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-6", "source": "1-5", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Two calls with the same shape: a cheap pre-check on a few identifying fields, then the full signup. Both return Accepted or Rejected in the body under HTTP 200. The answer is always in data.status. The HTTP status code says nothing about the decision. What will be needed from advertiser Key Purpose endpoint Base API URL. token API token sent in the request body. username Advertiser-provided value used as sourceDetail by the blueprint. partner_id Partner code sent as code. Flows Ping, POST /api/v1/leads/check. Name, national ID and address only. Returns data.status. Post, POST /api/v1/leads/signup. Full payload. Returns data.status, plus refNo and url when accepted. Calls POST {endpoint}/api/v1/leads/check POST {endpoint}/api/v1/leads/signup Content-Type: application/json format: application/json Credentials travel in the body: code is the partner identifier and token the key. There is no auth header. Request fields Dotted paths for nesting. Ping Field Required Value code yes {partner_id} token yes {token} sourceDetail no {send_id} personalInfo.firstName yes {g_name_first} personalInfo.lastName yes {g_name_last} personalInfo.birthNumber yes {g_id_national_number} residenceAddress.street yes {g_address_street} residenceAddress.houseNumber yes {g_address_street_number} residenceAddress.city yes {g_address_city} residenceAddress.zip yes {g_address_zip} residenceAddress.homeStatus yes {g_home_type}, see enums Post Everything above, plus: Field Required Value personalInfo.email yes {g_email} personalInfo.cellPhone yes {g_phone} in +420XXXXXXXXX personalInfo.identityCardNumber yes {g_id_card_number} personalInfo.incomeType yes {g_fin_type}, see enums incomeData.monthlyIncome yes toInt({g_fin_income}) incomeData.monthlyExpenses yes toInt({g_fin_expenses}) employerData.employer no {g_employer_name} employerData.jobTitle no {g_employ_position} employerData.employedTime no {g_employ_time}, see enums employerData.employerPhone no {g_employer_phone} in +420XXXXXXXXX employerData.employerAddress.city no {g_employer_address} bankData.bankAccountNumber yes {g_bank_account_number} bankData.bankCode yes {g_bank_account_code} contactAddress.street no {g_address_contact_street} contactAddress.houseNumber no {g_address_contact_street_number} contactAddress.city no {g_address_contact_city} contactAddress.zip no {g_address_contact_zip} sameAddress yes inverse of {g_address_contact_status} requestedAmount yes toInt({g_amount}) period yes toInt({g_period}) product yes loan ipAddress yes {ip_address} Phone numbers must be in international form. personalInfo.Invalid phone number format and employerData.Invalid phone number format are the two most common 400s, and they account for most of them together. The advertiser wants +420 followed by nine digits. sameAddress is inverted relative to a “contact address differs” checkbox, it is true when the addresses are the same. Amounts, periods and employment length go as integers, so convert inline in the HTTP node with toInt(...) rather than adding a Modify step for it. Enums incomeType: EMPLOYED, SELF_EMPLOYED, MATERNITY_LEAVE, PENSION, UNEMPLOYED, OTHER. homeStatus: HOME_OWNER, TENANT, DORMITORY, HOSTEL, MINISTRY, EMPLOYEE_BENEFIT, CO_OWNED. employedTime is a number of buckets: 1 under three months, 3 under a year, 4 one to two years, 5 two to five years, 8 over five years. Where the form’s bucket falls between two of the advertiser’s, choose the one that presents the lead as qualifying. Outcomes message is OK on every answer, accepted or not. It describes the call, not the decision, so nothing should branch on it. The decision is always data.status. Recognised by HTTP Meaning Reject reason Frequency data.status: Accepted 200 Approved , common data.status: Rejected 200 Refused, no reason given Unspecified common validationErrors ~ Invalid phone number format 400 Malformed phone Invalid Data occasional validationErrors ~ must be an email 400 Malformed e-mail Invalid Data rare data.status: Accepted, refNo and url null 200 Approved but no reference issued , see below rare HTML error page 500 Advertiser-side failure , (technical) rare Two things in that table need care. Accepted at the post arrives with and without refNo. Most acceptances carry a reference and a URL; a handful carry Accepted with both null. Those are not conversions there is nowhere to send the applicant and nothing to reconcile later, so the success condition needs url as well as the status. Rejected at the post also arrives with a refNo and a url. The advertiser has created a record and still refused. Branch on data.status, never on the presence of the URL alone. Rejected carries no reason at all. It is Unspecified, the largest bucket in the report and the thing to raise with the advertiser. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, approved: {status} equals 200 {parsedBody.data.status} equals Accepted Ping, refused: {status} equals 200 {parsedBody.data.status} equals Rejected Post, converted: {status} equals 200 {parsedBody.data.status} equals Accepted {parsedBody.data.url} is not empty Post, refused, the catch-all, scoped to the business field: {status} equals 200 {parsedBody.data.status} regex not match ^Accepted$ 400 carries a documented validationErrors list naming the failed field, so it gets a branch. 500 returns an HTML page and gets none. Stored values Parameter Source {external_id} {parsedBody.data.refNo} {redirect_url} {parsedBody.data.url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Hyperia (CZ) Advertiser Hyperia Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -760, "y": -120 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -760, "y": 310 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -570, "y": -120 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -350, "y": -120 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/v2/lead/create", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "lmc", "value": "{partner_id}" }, { "key": "access-token", "value": "{token}" }, { "key": "version_hash", "value": "{custom_version_hash}" } ], "body": [ { "key": "ssn", "value": "{data_nin}" }, { "key": "zip", "value": "{data_zip}" }, { "key": "city", "value": "{data_city}" }, { "key": "name", "value": "{data_first_name}" }, { "key": "email", "value": "{data_email}" }, { "key": "phone", "value": "{data_cell_phone}" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "number", "value": "{data_house_number}" }, { "key": "street", "value": "{data_street}" }, { "key": "surname", "value": "{data_last_name}" }, { "key": "bankCode", "value": "{data_bank_code}" }, { "key": "employer", "value": "{data_employer}" }, { "key": "loanTerm", "value": "{data_period}" }, { "key": "homeStatus", "value": "{data_home_status}" }, { "key": "incomeType", "value": "{data_income_type}" }, { "key": "employedTime", "value": "{data_employed_time}" }, { "key": "monthlyIncome", "value": "{data_monthly_income}" }, { "key": "monthlyExpenses", "value": "{data_expenses}" }, { "key": "bankAccountNumber", "value": "{data_account_number}" }, { "key": "identityCardNumber", "value": "{data_identity_card_number}" }, { "key": "lmSubParams.lmsub1", "value": "{eid}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": -110, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.data.process_id}" } ] } } }, { "id": "1-6", "type": "waitNode", "position": { "x": 80, "y": -220 }, "data": { "formData": { "active": true, "title": "Wait 20s", "subtitle": "", "type": "delay", "delayValue": 20, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-8", "type": "httpNode", "position": { "x": 280, "y": -220 }, "data": { "formData": { "active": true, "title": "Status", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/v2/lead/process-check-result/", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "lmc", "value": "{partner_id}" }, { "key": "process_id", "value": "{external_id}" }, { "key": "access-token", "value": "{token}" }, { "key": "version_hash", "value": "{custom_version_hash}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-9", "type": "setNode", "position": { "x": 520, "y": -300 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.result.url}" } ] } } }, { "id": "1-11", "type": "endNode", "position": { "x": 740, "y": -300 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-10", "type": "waitNode", "position": { "x": 500, "y": -90 }, "data": { "formData": { "active": true, "title": "Wait 5s", "subtitle": "", "type": "delay", "delayValue": 5, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-12", "type": "breakerNode", "position": { "x": 300, "y": 20 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": -90, "y": 60 }, "data": { "formData": { "active": true, "title": "Reject reason · Create", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.name}", "operator": "equals", "value": "Validation failed", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 140, "y": 80 }, "data": { "formData": { "active": true, "title": "Rejected · Create", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -540, "y": 310 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/v2/duplicity/check", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "access-token", "value": "{token}" }, { "key": "version_hash", "value": "{custom_version_hash}" } ], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "phone", "value": "{data_cell_phone}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "endNode", "position": { "x": -250, "y": 220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-4", "type": "modifyFieldNode", "position": { "x": -260, "y": 400 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.data.duplicate}", "operator": "equals", "value": "YES", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.data.result}", "operator": "equals", "value": "Validation failed", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-5", "type": "endNode", "position": { "x": 20, "y": 400 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" }, { "value": "{parsedBody.success}", "operator": "equals", "output": "true", "output2": "" }, { "value": "{parsedBody.data.process_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "422", "output2": "" }, { "value": "{parsedBody.success}", "operator": "equals", "output": "false", "output2": "" }, { "value": "{parsedBody.data.name}", "operator": "equals", "output": "Validation failed", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-12-1-8", "source": "1-12", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-8-1-9", "source": "1-8", "target": "1-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.success}", "operator": "equals", "output": "true", "output2": "" }, { "value": "{parsedBody.data.result.type}", "operator": "equals", "output": "2", "output2": "" }, { "value": "{parsedBody.data.result.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-8-1-10", "source": "1-8", "target": "1-10", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.success}", "operator": "equals", "output": "true", "output2": "" }, { "value": "{parsedBody.data.result.type}", "operator": "equals", "output": "0", "output2": "" } ] } }, { "id": "edge-1-9-1-11", "source": "1-9", "target": "1-11", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-10-1-12", "source": "1-10", "target": "1-12", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.success}", "operator": "equals", "output": "true", "output2": "" }, { "value": "{parsedBody.data.duplicate}", "operator": "equals", "output": "NO", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "regex_match", "output": "^(200|422)$", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "\\\"duplicate\\\"\\s*:\\s*\\\"YES\\\"|\\\"result\\\"\\s*:\\s*\\\"Validation failed\\\"", "output2": "" } ] } }, { "id": "edge-2-4-2-5", "source": "2-4", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details A lead broker rather than a lender: the create call starts an asynchronous process and the answer arrives later from a separate status endpoint. The redirect URL only exists once the process has finished. Two things shape the build. The decision is data.result.type, a number, not a string. And the process is genuinely slow, so the loop is the integration. What will be needed from advertiser Key Purpose endpoint Base API URL for the selected environment. token Value for the access-token query parameter. partner_id Partner code sent as lmc. custom_version_hash Form version hash sent as version_hash. Flows Ping, POST /v2/duplicity/check. E-mail and phone only. Answers duplicate: YES or NO. Post, POST /v2/lead/create starts the process and returns a process_id, then GET /v2/lead/process-check-result is polled until it resolves. Calls POST {endpoint}/v2/duplicity/check POST {endpoint}/v2/lead/create GET {endpoint}/v2/lead/process-check-result/ Content-Type: application/json format: application/json Credentials travel as query parameters on every call: access-token, lmc for the partner code, and version_hash identifying the form version in use. The advertiser also exposes /test-v2/... twins of each endpoint. Point {endpoint} at whichever environment the integration is running in rather than hardcoding the path. GET /v2/lead/get-inputs returns the fields the current form version requires, which is worth calling once when the version hash changes rather than per lead. Request fields Ping Field Required Value email yes {g_email} phone yes {g_phone} Post Field Required Value name yes {g_name_first} surname yes {g_name_last} ssn yes {g_id_national_number} identityCardNumber yes {g_id_card_number} email yes {g_email} phone yes {g_phone} street yes {g_address_street} number yes {g_address_street_number} city yes {g_address_city} zip yes {g_address_zip} homeStatus yes {g_home_type} incomeType yes {g_fin_type}, see enums monthlyIncome yes {g_fin_income} monthlyExpenses yes {g_fin_expenses} employer no {g_employer_name} employedTime no {g_employ_time} bankAccountNumber yes {g_bank_account_number} bankCode yes {g_bank_account_code} amount yes {g_amount} loanTerm yes {g_period} lmSubParams.lmsub1 yes {send_id} lmSubParams.lmsub1 is the reference Hyperia echoes back in postbacks, so it has to be a value you can match on later. Enums incomeType: EMPLOYED, SELF_EMPLOYED, MATERNITY_LEAVE, PENSION, UNEMPLOYED, OTHER. The accepted set for homeStatus, employedTime and bankCode depends on the form version, which is what version_hash identifies. Take them from get-inputs for the version in use rather than from a fixed list. Outcomes Every response is wrapped in success plus a data object. success describes the call, not the decision, so it is a precondition rather than a branch. At the status endpoint the decision is data.result.type, a number: type Meaning 0 Still processing, ask again 2 Finished, data.result.url holds the redirect Recognised by HTTP Meaning Reject reason Frequency data.duplicate: NO 200 Not on file, proceed common data.name: Processed + process_id 201 Process started occasional data.result.type: 2 + url 200 Accepted common data.result.type: 0 200 Still processing (loop) occasional data.duplicate: YES 200 Already on file Duplicate documented only data.result: Validation failed at the ping 422 Payload refused, field named Invalid Data rare data.name: Validation failed at the create 422 Payload refused, field named Invalid Data rare The 422 body carries data.errors keyed by field name, for example {"email": ["Zadaný e-mail neexistuje"]} and {"zip": ["PSČ nemá správný formát"]}. Pass the whole body through in {reason_detail}; a run of the same field name means the form needs fixing rather than the blueprint. Note that a validation failure at the ping and at the create put their message in different places, data.result and data.name respectively. Both are Validation failed. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, not on file: {status} equals 200 {parsedBody.success} equals true {parsedBody.data.duplicate} equals NO Ping, refused, matched against {body} so both the duplicate and the validation shape are covered by one condition: {status} regex match ^(200|422)$ {body} regex match "duplicate"\s*:\s*"YES"|"result"\s*:\s*"Validation failed" Create, started: {status} equals 201 {parsedBody.success} equals true {parsedBody.data.process_id} is not empty Status, finished: {status} equals 200 {parsedBody.success} equals true {parsedBody.data.result.type} equals 2 {parsedBody.data.result.url} is not empty Status, still processing, back through Wait and Breaker: {parsedBody.data.result.type} equals 0 The first wait is long, because the process takes tens of seconds to resolve. Watch the synchronous limit: the applicant is on a loading screen for the whole loop, and the wait plus the Breaker’s repetitions have to fit inside it. Every loop carries a Breaker with its count in the title. Stored values Parameter Source {external_id} {parsedBody.data.process_id} from the create {redirect_url} {parsedBody.data.result.url} from the status call Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Kamali (CZ) Advertiser Kamali Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 220 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": -180 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -420, "y": 220 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "2" }, { "source": "{data_income_type}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "15000", "value2": "", "modification": "replace", "pattern": "", "output": "15000" }, { "source": "{data_requested_amount}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_identity_card_number}", "fields": [ { "source": "{data_identity_card_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_city}", "fields": [ { "source": "{data_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_zip}", "fields": [ { "source": "{data_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_street}", "fields": [ { "source": "{data_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_house_number}", "fields": [ { "source": "{data_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_monthly_income}", "fields": [ { "source": "{data_monthly_income}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_expenses}", "fields": [ { "source": "{data_expenses}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_account_number}", "fields": [ { "source": "{data_account_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_bank_code}", "fields": [ { "source": "{data_bank_code}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -180, "y": 220 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/Clients/ClientChecks", "timeout": 30, "format": "application/json", "parser": "json", "notsend": "null", "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "name", "value": "{data_first_name}" }, { "key": "email", "value": "{data_email}" }, { "key": "surname", "value": "{data_last_name}" }, { "key": "addressCity", "value": "{data_city}" }, { "key": "nationality", "value": "1" }, { "key": "phoneNumber", "value": "{data_cell_phone}" }, { "key": "subjectCode", "value": "{token}" }, { "key": "addressStreet", "value": "{data_street}" }, { "key": "amtLoanAmount", "value": "{data_requested_amount}" }, { "key": "documentNumber", "value": "{data_identity_card_number}" }, { "key": "personalNumber", "value": "{data_nin}" }, { "key": "amtClientIncomes", "value": "{data_monthly_income}" }, { "key": "addressPostalCode", "value": "{data_zip}" }, { "key": "amtClientExpenses", "value": "{data_expenses}" }, { "key": "bankAccountNumber", "value": "{data_account_number}" }, { "key": "addressMailingCity", "value": "{data_contact_city}" }, { "key": "addressStreetNumber", "value": "{data_house_number}" }, { "key": "bankAccountBankCode", "value": "{data_bank_code}" }, { "key": "addressMailingStreet", "value": "{data_contact_street}" }, { "key": "clientIncomesSourceCode", "value": "{data_income_type}" }, { "key": "addressMailingPostalCode", "value": "{data_contact_zip}" }, { "key": "addressMailingStreetNumber", "value": "{data_contact_house_number}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "endNode", "position": { "x": -22.910723984683, "y": 109.66171480503 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 80, "y": 300 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 320, "y": 300 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -420, "y": -180 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "2" }, { "source": "{data_income_type}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "15000", "value2": "", "modification": "replace", "pattern": "", "output": "15000" }, { "source": "{data_requested_amount}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_identity_card_number}", "fields": [ { "source": "{data_identity_card_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_city}", "fields": [ { "source": "{data_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_zip}", "fields": [ { "source": "{data_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_street}", "fields": [ { "source": "{data_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_house_number}", "fields": [ { "source": "{data_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_monthly_income}", "fields": [ { "source": "{data_monthly_income}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_expenses}", "fields": [ { "source": "{data_expenses}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_account_number}", "fields": [ { "source": "{data_account_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -180, "y": -180 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/Clients", "timeout": 30, "format": "application/json", "parser": "json", "notsend": "null", "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "name", "value": "{data_first_name}" }, { "key": "email", "value": "{data_email}" }, { "key": "surname", "value": "{data_last_name}" }, { "key": "addressCity", "value": "{data_city}" }, { "key": "nationality", "value": "1" }, { "key": "phoneNumber", "value": "{data_cell_phone}" }, { "key": "subjectCode", "value": "{token}" }, { "key": "addressStreet", "value": "{data_street}" }, { "key": "amtLoanAmount", "value": "{data_requested_amount}" }, { "key": "documentNumber", "value": "{data_identity_card_number}" }, { "key": "personalNumber", "value": "{data_nin}" }, { "key": "amtClientIncomes", "value": "{data_monthly_income}" }, { "key": "addressPostalCode", "value": "{data_zip}" }, { "key": "amtClientExpenses", "value": "{data_expenses}" }, { "key": "bankAccountNumber", "value": "{data_account_number}" }, { "key": "addressMailingCity", "value": "{data_contact_city}" }, { "key": "addressStreetNumber", "value": "{data_house_number}" }, { "key": "bankAccountBankCode", "value": "{data_bank_code}" }, { "key": "addressMailingStreet", "value": "{data_contact_street}" }, { "key": "clientIncomesSourceCode", "value": "{data_income_type}" }, { "key": "addressMailingPostalCode", "value": "{data_contact_zip}" }, { "key": "addressMailingStreetNumber", "value": "{data_contact_house_number}" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": 80, "y": -180 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{headers.Location}" }, { "key": "{external_id}", "value": "{parsedBody.id}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 320, "y": -180 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": 178.37917367995, "y": 82.360639825252 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 373.78438025996, "y": 84.658036535246 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "406", "output2": "" } ] } }, { "id": "edge-1-5-1-6", "source": "1-5", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" }, { "value": "{parsedBody.id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{headers.Location}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details A REST API where the HTTP status code is the answer and the body is usually empty. That is the whole integration in one line: the pre-check returns 200 or 406 with no body at all, and the create returns 201 with the new client’s ID and the redirect in the Location header rather than in the response body. Expect the great majority of leads to be refused at the pre-check, with nothing said about why. What will be needed from advertiser Key Purpose endpoint Base API URL. token Advertiser subject code sent as subjectCode. Flows Ping, POST /Clients/ClientChecks. Predicts whether the client would be approved. Nothing is stored. Post, POST /Clients. Creates the client. Returns id and a Location header. Creating a client does not mean the client was approved. It means the record exists and the applicant can be sent to the URL in Location to continue. The status code on the create says which kind of applicant this is, and the Location header confirms it: HTTP Location Meaning 201 /zadost-prvni-partner?kod=... New applicant, a fresh application is opened 200 /prihlaseni?prihlasit-se Already a customer, sent to sign in Roughly one create in seven comes back 200. The record already existed, so nothing new was opened and the kod parameter that carries the application is absent. Calls POST {endpoint}/Clients/ClientChecks POST {endpoint}/Clients Content-Type: application/json format: application/json notsend: null Authentication is subjectCode in the body rather than a header or a token. Request fields Both calls take the same body. The advertiser is explicit that the prediction improves with more data, so send everything the form collects. Field Required Value subjectCode yes {token} name yes {g_name_first} surname yes {g_name_last} phoneNumber yes {g_phone} email yes {g_email} personalNumber yes {g_id_national_number}, no slash documentNumber no {g_id_card_number} nationality yes 1 Czech, 2 other addressStreet no {g_address_street} addressStreetNumber no {g_address_street_number} addressCity no {g_address_city} addressPostalCode no {g_address_zip} addressMailingStreet no {g_address_contact_street} addressMailingStreetNumber no {g_address_contact_street_number} addressMailingCity no {g_address_contact_city} addressMailingPostalCode no {g_address_contact_zip} clientIncomesSourceCode no {g_fin_type}, see enums amtClientIncomes no {g_fin_income} amtClientExpenses no {g_fin_expenses} amtLoanAmount no {g_amount}, capped at 15 000 bankAccountNumber no {g_bank_account_number} bankAccountBankCode no {g_bank_account_code} Optional fields the form leaves empty should be dropped with do-not-send rather than sent as empty strings. On capping the amount Where a request exceeds 15 000, send 15 000 rather than the requested figure, but agree it with them first. Translating a higher request down is right only when they would otherwise reject the lead outright. Where they would have made a smaller offer on their own, send what the applicant actually asked for and let them answer. Enums clientIncomesSourceCode is a numeric ID, 1 for employed and 2 for self-employed, with the current list at GET /Parameters/IncomeSources. There are only two, so anything else has no option: drop the field with do-not-send rather than forcing a value the applicant did not give. bankAccountBankCode likewise comes from GET /Parameters/BankId. Fetch both lists once and write the mapping into the blueprint rather than calling them per lead. Outcomes Recognised by HTTP Meaning Reject reason Frequency empty body 200 Pre-check passed occasional id present, Location ~ zadost-prvni-partner 201 New applicant created common empty body 406 Pre-check refused, no reason given Unspecified common id present, Location ~ prihlaseni 200 Already a customer, sent to sign in Existing Customer occasional empty body 400 Payload refused, no detail given Invalid Data rare HTML 404 Not Found 404 Wrong endpoint or path rare Errors[].procedure: dbo.asmRCM_ISIR_CheckCustomer 500 Advertiser’s database failed rare 406 is the whole rejection vocabulary. The advertiser documents it as “client was not approved or repaid”, and returns no body with it. There is nothing to map beyond Unspecified, and {reason_detail} will be empty because {body} is empty. That is a report line worth taking to them: several thousand leads refused, no reason given, please send reason codes. The 500 returns a raw SQL Server exception naming an internal stored procedure. It is their fault, not the lead’s, and it gets no branch. The 404 returns an HTML page rather than JSON, which means the request never reached the API. Also no branch. The 200 on the create is Existing Customer, not Duplicate. Duplicate means the same application already exists; here it is the person who is already on file, and Kamali still offers them a way in. Whether that counts as a sale is a contract question rather than an API one, so the branch is worth keeping separate from the plain refusal either way. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching There is no business field to branch on, so here the status code is all there is. That is the exception rather than the rule, and it is only safe because the advertiser documents each code as a decision. Ping, passed: {status} equals 200 Ping, refused: {status} equals 406 Post, created: {status} equals 201 {parsedBody.id} is not empty {headers.Location} is not empty Post, already a customer: {status} equals 200 {parsedBody.id} is not empty {headers.Location} is not empty 400, 404 and 500 get no branch. Stored values Parameter Source {external_id} {parsedBody.id} from the create {redirect_url} {headers.Location} from the create The redirect is in a header rather than the body, so it is read from {headers.Location} and not from {parsedBody}. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Movinero (CZ) Advertiser Movinero Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -560, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -360, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "regex_not_match", "value": "^(full-time|self-employed|parental|pension|unemployed|other)$", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "nevyplněno" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{data_zip}" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{data_city}" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{data_street}" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{data_house_number}" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "40000", "value2": "", "modification": "replace", "pattern": "", "output": "40000" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -140, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/webapi/v1/loan/register", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "{token}" } ], "query": [], "body": [ { "key": "client.city", "value": "{data_city}" }, { "key": "client.email", "value": "{data_email}" }, { "key": "client.phone", "value": "{data_cell_phone}" }, { "key": "loan.loan_sum", "value": "{data_requested_amount}" }, { "key": "client.address", "value": "{data_street}" }, { "key": "client.employer", "value": "{data_employer}" }, { "key": "client.password", "value": "{token}" }, { "key": "client.last_name", "value": "{data_last_name}" }, { "key": "client.origin_ip", "value": "{ip_address}" }, { "key": "loan.loan_period", "value": "{data_period}" }, { "key": "client.first_name", "value": "{data_first_name}" }, { "key": "client.income_type", "value": "{data_income_type}" }, { "key": "client.neto_income", "value": "{data_monthly_income}" }, { "key": "client.personal_id", "value": "{data_nin}" }, { "key": "client.bank_account", "value": "{data_account_number}" }, { "key": "client.cz_bank_code", "value": "{data_bank_code}" }, { "key": "client.house_number", "value": "{data_house_number}" }, { "key": "client.mailing_city", "value": "{data_contact_city}" }, { "key": "client.postal_index", "value": "{data_zip}" }, { "key": "client.id_card_number", "value": "{data_identity_card_number}" }, { "key": "client.mailing_address", "value": "{data_contact_street}" }, { "key": "client.mailing_house_number", "value": "{data_contact_house_number}" }, { "key": "client.mailing_postal_index", "value": "{data_contact_zip}" }, { "key": "client.password_confirmation", "value": "{token}" }, { "key": "client.cz_bank_account_prefix", "value": "000000" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 100, "y": 40 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.redirect_uri}" }, { "key": "{external_id}", "value": "{parsedBody.customer_number}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 320, "y": 40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 100, "y": 220 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.substate}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "already registered", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "same email", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "již zaregistrován", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "execution report", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "age lower", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "not registered bank", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "není správné", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "A26", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "A27", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.substate}", "operator": "contains", "value": "income lower than limit", "value2": "", "modification": "replace", "pattern": "", "output": "Low Income" }, { "source": "{parsedBody.substate.errors.0.message}", "operator": "contains", "value": "již zaregistrován", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.substate.errors.0.message}", "operator": "contains", "value": "není správné", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.substate}" }, { "source": "{parsedBody.substate.errors.0.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.substate.errors.0.message}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 320, "y": 220 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "Accepted", "subtitle": "", "conditions": [ { "value": "{parsedBody.accepted}", "operator": "contains", "output": "true", "output2": "" }, { "value": "{status}", "operator": "equals", "output": "201", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "Rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.accepted}", "operator": "equals", "output": "false", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Also trades as VivaCredit. One call registers the customer and decides. There is no ping. The response is unusual and worth understanding before anything else: acceptance and rejection have different body shapes and different status codes, and the rejection reason arrives in a field called substate that is sometimes a string and sometimes an object. What will be needed from advertiser Key Purpose endpoint Base API URL. token Authorization token. Flows Post, POST /webapi/v1/loan/register. Registers and decides. Calls POST {endpoint}/webapi/v1/loan/register Authorization: {token} Content-Type: application/json format: application/json The token goes in Authorization with no scheme prefix, no Bearer, no Token. Request fields Dotted paths for nesting, client and loan. Field Required Value client.first_name yes {g_name_first} client.last_name yes {g_name_last} client.email yes {g_email}, must be unique client.phone yes {g_phone}, nine digits client.personal_id yes {g_id_national_number}, must be unique and valid client.id_card_number yes {g_id_card_number} client.income_type yes {g_fin_type}, see enums client.neto_income yes {g_fin_income} client.employer yes {g_employer_name} client.address yes {g_address_street} client.house_number yes {g_address_street_number} client.city yes {g_address_city} client.postal_index yes {g_address_zip} client.mailing_address yes {g_address_contact_street} client.mailing_house_number yes {g_address_contact_street_number} client.mailing_city yes {g_address_contact_city} client.mailing_postal_index yes {g_address_contact_zip} client.bank_account yes {g_bank_account_number}, must be unique client.cz_bank_code yes {g_bank_account_code} client.cz_bank_account_prefix yes {g_bank_account_prefix}, 000000 when there is none client.password yes a fixed value the integration controls client.password_confirmation yes the same fixed value client.origin_ip yes {ip_address} loan.loan_sum yes {g_amount}, capped at 40 000 loan.loan_period yes {g_period} client.next_payday no {g_period_end} as yyyy-MM-dd, defaults to today The mailing address fields are mandatory even when they are the same as the permanent one. Fill them from the permanent address when the form leaves them empty rather than sending blanks, an empty required field is a rejected request here. employer is mandatory too, including for people who have no employer. Fill it with a placeholder rather than dropping it. password and password_confirmation create the customer’s account. Any stable value the integration controls works. On capping the amount Where a request exceeds the advertiser’s maximum, send the maximum rather than the requested figure, but agree it with them first. Translating a higher request down is right only when they would otherwise reject the lead outright. Where they would have made a smaller offer on their own, send what the applicant actually asked for and let them answer. This is the one place the general rule bends: amount, term and product are the request itself, so they are normally passed through untouched. Enums client.income_type: EMPLOYED, SELF_EMPLOYED, PENSION, MATERNITY_LEAVE, OTHER. There is no unemployed option, map it to OTHER. Outcomes substate has two shapes. Usually it is a plain string. For validation failures it is an object holding an errors list, and the useful text sits at {parsedBody.substate.errors.0.message}, with the index, or it does not resolve at all. Set {reason_detail} from {body} on an unconditional row so both shapes are covered, then add the indexed path as an extra conditional row on top. Recognised by HTTP Meaning Reject reason Frequency accepted: true + redirect_uri 201 Accepted , occasional substate ~ already registered 200 Already a customer Duplicate common substate ~ customer with same email 200 E-mail on file Duplicate occasional substate ~ [A26] 200 Knockout criterion Not Eligible occasional substate ~ [A27 - local authorities check] 200 Knockout criterion Not Eligible occasional substate ~ age lower than limit 200 Below the age limit Age occasional substate ~ execution report 200 Enforcement on record Debt Collection occasional substate ~ income lower than limit 200 Income below threshold Low Income rare substate ~ not registered bank 200 Bank not supported Invalid Data occasional substate.errors[].message ~ Číslo bankovního účtu není správné 200 Malformed account number Invalid Data rare substate.errors[].message ~ bankovní účet je u nás již zaregistrován 200 Account already on file Duplicate rare substate: internal server error 500 Advertiser-side failure , (technical) rare substate has two shapes. Usually it is a plain string. For validation failures it is an object holding an errors list, and the useful text is at {parsedBody.substate.errors.0.message}, with the index, or it does not resolve at all. Set {reason_detail} from {body} on an unconditional row so both shapes are covered, then add the indexed path as an extra conditional row on top. [A26] and [A27] are the advertiser’s own knockout codes. They name a condition the lead failed that you could not have checked in advance, which is what Not Eligible is for. Everything that merely says no goes to Unspecified instead. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted: {status} equals 201 {parsedBody.accepted} contains true Rejected, a business answer under 200: {status} equals 200 {parsedBody.accepted} equals false 500 and 503 carry no business result and get no branch. Stored values Parameter Source {external_id} {parsedBody.customer_number} {redirect_url} {parsedBody.redirect_uri} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to PůjčkaPlus (CZ) Advertiser PůjčkaPlus Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Platform CreditOnline Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -560, "y": -180 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -560, "y": 200 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -400, "y": -180 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "endNode", "position": { "x": -80, "y": -240 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": -80, "y": -100 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.person_code}", "operator": "regex_match", "value": "^(registered|Registered)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.email}", "operator": "regex_match", "value": "^(registered|Registered)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.mob_phone}", "operator": "regex_match", "value": "^(registered|Registered)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.id_number}", "operator": "regex_match", "value": "^(registered|Registered)$", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-5", "type": "endNode", "position": { "x": 80, "y": -100 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -400, "y": 200 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec - plný pracovní úvazek" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "OSVČ/Podnikatel" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "Mateřská/Rodičovská" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "Starobní/Invalidní důchodce" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "Nezaměstnaný" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec - zkrácený pracovní úvazek" } ] }, { "fieldName": "{data_different_contact_address}", "fields": [ { "source": "{data_different_contact_address}", "operator": "regex_match", "value": "^(1|true|True|TRUE|yes|Yes|YES|on|On|ON)$", "value2": "", "modification": "replace", "pattern": "", "output": "0" }, { "source": "{data_different_contact_address}", "operator": "regex_match", "value": "^(0|false|False|FALSE|no|No|NO|off|Off|OFF)$", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_different_contact_address}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -240, "y": 200 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.registerClient", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.ref", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.city2", "value": "{data_contact_city}" }, { "key": "data.costs", "value": "{data_expenses}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.house2", "value": "{data_contact_house_number}" }, { "key": "data.income", "value": "{data_monthly_income}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.address2", "value": "{data_contact_street}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.zipcode2", "value": "{data_contact_zip}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.marketing", "value": "0" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.workplace", "value": "{data_employer}" }, { "key": "data.contract_c", "value": "1" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.other_income", "value": "{data_income_type}" }, { "key": "data.chk9_formular", "value": " " }, { "key": "data.create_credit", "value": "{data_requested_amount}-{data_period}" }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" }, { "key": "data.address_different", "value": "{data_different_contact_address}" }, { "key": "data.chk10_vop_smlouva", "value": "Potvrzuji, že jsem si přečetl(a) a souhlasím s VOP a podmínkami smlouvy o úvěru" }, { "key": "data.workplace_position", "value": "{data_job_title}" }, { "key": "data.chk11_politicky_ex_osoba", "value": "Prohlašuji, že nejsem politicky exponovanou osobou a mnou uvedené informace jsou pravdivé" }, { "key": "data.chk12_osobni_udaje_registry", "value": "Souhlasím se zpracováním mých osobních údajů pro úvěrové registry" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": -80, "y": 140 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.url}" }, { "key": "{external_id}", "value": "{parsedBody.credit_id}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 80, "y": 140 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -80, "y": 280 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.err}", "operator": "contains", "value": "Already registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Age check failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Nespráv", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Price does not exist", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 80, "y": 280 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.person_code}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.email}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.mob_phone}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.id_number}", "operator": "equals", "output": "notFound", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{body}", "operator": "regex_not_match", "output": "(?=.*\"ok\"\\s*:\\s*1)(?=.*\"person_code\"\\s*:\\s*\"notFound\")(?=.*\"email\"\\s*:\\s*\"notFound\")(?=.*\"mob_phone\"\\s*:\\s*\"notFound\")(?=.*\"id_number\"\\s*:\\s*\"notFound\")", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "(?:\"person_code\"\\s*:\\s*\"(?:declined|age_check_failed|registered|Registered)\"|\"(?:email|mob_phone|id_number)\"\\s*:\\s*\"(?:registered|Registered)\")", "output2": "" } ] } }, { "id": "edge-1-4-1-5", "source": "1-4", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{body}", "operator": "regex_not_match", "output": "(?=.*\"ok\"\\s*:\\s*1)(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))(?=.*\"credit_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))", "output2": "" }, { "value": "{body}", "operator": "regex_match", "output": "(?:Already registered|Age check failed|Nespráv|Price does not exist)", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details PůjčkaPlus uses the CreditOnline RPC backend and currently has only the new clients flow. Ping checks whether the person is new; Post calls registerClient, and that same RPC request also creates the credit through create_credit. There is no separate /application call in the current blueprint. What will be needed from advertiser Key Purpose endpoint CreditOnline tenant API base URL. username RPC login. password RPC password. Flows New clients — Ping, POST /?RPC=agents.checkPersonalData. The client may continue only when all four checked identity fields are notFound. New clients — Post, POST /?RPC=agents.registerClient. Registers the client and creates the requested credit in one call. Success returns both credit_id and url. Calls POST {endpoint}/?RPC=agents.checkPersonalData POST {endpoint}/?RPC=agents.registerClient Content-Type: application/x-www-form-urlencoded; charset=UTF-8 format: login-data-pass The form body has exactly three top-level keys: login, pass and data. login is {username}, pass is {password}, and the actual advertiser payload is written as data.* fields. Do not construct the form envelope manually. Response model checkPersonalData uses HTTP 200 for both accepted and refused business outcomes. The Ping decision therefore comes from ok and personalData, not from HTTP status alone. The current PůjčkaPlus blueprint cares about the four identity states person_code, email, mob_phone and id_number: all four must be notFound for a new client to continue. A registered state means the person is already known. The RPC backend can also return an authentication error as HTTP 200 with an err payload and without a usable ok/personalData. Treat that as a technical credentials failure, not as a business rejection or Ping success. Unlike the usual CreditOnline three-step pattern, PůjčkaPlus does not call a separate application endpoint. Its registerClient request includes create_credit, so one successful RPC response contains the registration and conversion result together. The current Post only succeeds when ok: 1, customer_id, credit_id and url are all present. Registration/business failures are returned through err; only the concrete texts listed under Outcomes are mapped to reject reasons. Request fields Ping Field Required Value person_code yes {g_id_national_number} mob_phone yes {g_phone} email yes {g_email} surname yes {g_name_last} realname yes {g_name_first} id_number yes {g_id_card_number} address yes {g_address_street} house yes {g_address_street_number} city yes {g_address_city} zipcode yes {g_address_zip} Post The registration request repeats the identity/address fields and adds: Field Required Value ip yes {ip_address} ref yes source identifier used by the blueprint income yes {g_fin_income} costs no {g_fin_expenses} other_income yes mapped income type workplace no {g_employer_name} workplace_position no {g_employ_position} account_number yes {g_bank_account_number}/{g_bank_account_code} address2, house2, city2, zipcode2 when different contact address fields address_different conditionally inverted “contact address differs” flag create_credit yes {g_amount}-{g_period} contract_c yes 1 marketing yes 0 in the current blueprint chk9_formular, chk10_vop_smlouva, chk11_politicky_ex_osoba, chk12_osobni_udaje_registry yes advertiser consent/declaration values from the blueprint Empty optional contact-address fields are omitted. Transforms Income types are translated to the advertiser labels: full-time → Zaměstnanec - plný pracovní úvazek, self-employed → OSVČ/Podnikatel, parental → Mateřská/Rodičovská, pension → Starobní/Invalidní důchodce, unemployed → Nezaměstnaný, other → Zaměstnanec - zkrácený pracovní úvazek. The contact-address flag is inverted: a value meaning “different address” becomes 0, a value meaning “same address” becomes 1. If the source flag is empty it is omitted rather than guessed. Outcomes Recognised by HTTP Meaning Reject reason Ping: ok: 1 and all four identity fields notFound 200 New client, proceed Ping: any identity field registered / Registered 200 Already known Existing Customer Ping: person_code: age_check_failed 200 Age check failed Age Ping: explicit declined 200 Refused without a more specific reason Unspecified Post: ok: 1 + non-empty customer_id, credit_id, url 200 Registered and credit created err contains Already registered 200 Already known Existing Customer err contains Age check failed 200 Age check failed Age err contains Nespráv 200 Invalid input Invalid Data err contains Price does not exist 200 Requested combination is unavailable Product Mismatch {reason_detail} is the raw {body}. Technical responses outside the recognised HTTP-200 business shapes are left as errors rather than re-labelled as business rejections. Branching Ping accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.person_code} equals notFound {parsedBody.personalData.email} equals notFound {parsedBody.personalData.mob_phone} equals notFound {parsedBody.personalData.id_number} equals notFound Post accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.customer_id} is not empty {parsedBody.credit_id} is not empty {parsedBody.url} is not empty Stored values Parameter Source {external_id} {parsedBody.credit_id} {redirect_url} {parsedBody.url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Rerum (CZ) Advertiser Rerum Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Platform CreditOnline Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint Blueprint for new customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -700, "y": 180 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -760, "y": -220 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -270, "y": 180 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "endNode", "position": { "x": 30, "y": 40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": 20, "y": 250 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registrator|Klient)$", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "wrong_person_code", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 300, "y": 250 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-5", "type": "breakerNode", "position": { "x": -110, "y": 440 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "1-7", "type": "waitNode", "position": { "x": 130, "y": 440 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -560, "y": -220 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec - plný pracovní úvazek" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "OSVČ/Podnikatel" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "Mateřská/Rodičovská" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "Starobní/Invalidní důchodce" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "Nezaměstnaný" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec - zkrácený pracovní úvazek" }, { "source": "{data_income_type}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{created_date}", "fields": [ { "source": "{created_date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+30 days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "Y-m-d" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_different_contact_address}", "fields": [ { "source": "{data_different_contact_address}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_job_title}", "fields": [ { "source": "{data_job_title}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -300, "y": -220 }, "data": { "formData": { "active": true, "title": "Create", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.registerClient", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": "null", "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.ref", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.city2", "value": "{data_contact_city}" }, { "key": "data.costs", "value": "{data_expenses}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.amount", "value": "{data_requested_amount}" }, { "key": "data.house2", "value": "{data_contact_house_number}" }, { "key": "data.income", "value": "{data_monthly_income}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.address2", "value": "{data_contact_street}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.zipcode2", "value": "{data_contact_zip}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.marketing", "value": "0" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.workplace", "value": "{data_employer}" }, { "key": "data.contract_c", "value": "1" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.other_income", "value": "{data_income_type}" }, { "key": "data.chk9_formular", "value": " " }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" }, { "key": "data.address_different", "value": "{data_different_contact_address}" }, { "key": "data.chk10_vop_smlouva", "value": "Potvrzuji, že jsem si přečetl(a) a souhlasím s VOP a podmínkami smlouvy o úvěru" }, { "key": "data.workplace_position", "value": "{data_job_title}" }, { "key": "data.chk11_politicky_ex_osoba", "value": "Prohlašuji, že nejsem politicky exponovanou osobou a mnou uvedené informace jsou pravdivé" }, { "key": "data.chk12_osobni_udaje_registry", "value": "Souhlasím se zpracováním mých osobních údajů pro úvěrové registry" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": -20, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.customer_id}" } ] } } }, { "id": "2-6", "type": "httpNode", "position": { "x": 230, "y": -220 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/creditLine/application", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "_method", "value": "post" }, { "key": "apiLoan", "value": "cz" }, { "key": "paydays", "value": "{created_date}" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "{data_requested_amount}" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "2-8", "type": "setNode", "position": { "x": 500, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "2-10", "type": "endNode", "position": { "x": 760, "y": -220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -36.540460702626, "y": -82.724966468943 }, "data": { "formData": { "active": true, "title": "Reject reason · Create", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 235.64724718352, "y": -21.786427038214 }, "data": { "formData": { "active": true, "title": "Rejected · Create", "subtitle": "", "success": "failed" } } }, { "id": "2-9", "type": "modifyFieldNode", "position": { "x": 500, "y": 20 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-11", "type": "endNode", "position": { "x": 760, "y": 20 }, "data": { "formData": { "active": true, "title": "Rejected · Post", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-2", "source": "1-7", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.person_code}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.email}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.mob_phone}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.id_number}", "operator": "equals", "output": "notFound", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "regex_not_match", "output": "^CSAS Evaluation is in progress$", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"person_code\"\\s*:\\s*\"notFound\")(?=.*\"email\"\\s*:\\s*\"notFound\")(?=.*\"mob_phone\"\\s*:\\s*\"notFound\")(?=.*\"id_number\"\\s*:\\s*\"notFound\")", "output2": "" } ] } }, { "id": "edge-1-2-1-5", "source": "1-2", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "CSAS Evaluation is in progress", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "(\"ok\"\\s*:|\"err\"\\s*:\\s*\\[)", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"ok\"\\s*:\\s*1)(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-8", "source": "2-6", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-6-2-9", "source": "2-6", "target": "2-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "\"status\"\\s*:", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"status\"\\s*:\\s*200)(?=.*\"data\"\\s*:\\s*\\{[^}]*\"status\"\\s*:\\s*\"success\")(?=.*\"credit_id\"\\s*:\\s*\"[^\"]+\")(?=.*\"url\"\\s*:\\s*\"[^\"]+\")", "output2": "" } ] } }, { "id": "edge-2-8-2-10", "source": "2-8", "target": "2-10", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-9-2-11", "source": "2-9", "target": "2-11", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Blueprint for registered customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -687, "y": 174 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": -220 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -375, "y": 181 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "setNode", "position": { "x": -100, "y": 40 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.personalData.customer_id}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 160, "y": 40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": -80, "y": 260 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Klient", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "wrong_person_code", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 190, "y": 260 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-8", "type": "waitNode", "position": { "x": -140, "y": 430 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-5", "type": "breakerNode", "position": { "x": -400, "y": 430 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -380, "y": -220 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/creditLine/application", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "_method", "value": "post" }, { "key": "apiLoan", "value": "cz" }, { "key": "paydays", "value": "{created_date}" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "{data_requested_amount}" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": -80, "y": -320 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 180, "y": -320 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -60, "y": -120 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 190, "y": -120 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -500, "y": -220 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{created_date}", "fields": [ { "source": "{created_date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+30 days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "Y-m-d" } ] } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-8-1-2", "source": "1-8", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.info}", "operator": "contains", "output": "Loan creation was approved", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "Registrator", "output2": "" }, { "value": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "regex_not_match", "output": "^CSAS Evaluation is in progress$", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"info\"\\s*:\\s*\"[^\"]*Loan creation was approved)(?=.*\"addinfo\"\\s*:\\s*\"Registrator\")(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))", "output2": "" } ] } }, { "id": "edge-1-2-1-5", "source": "1-2", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "pending", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "CSAS Evaluation is in progress", "output2": "" } ] } }, { "id": "edge-1-3-1-6", "source": "1-3", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-8", "source": "1-5", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "\"status\"\\s*:", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"status\"\\s*:\\s*200)(?=.*\"data\"\\s*:\\s*\\{[^}]*\"status\"\\s*:\\s*\"success\")(?=.*\"credit_id\"\\s*:\\s*\"[^\"]+\")(?=.*\"url\"\\s*:\\s*\"[^\"]+\")", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Blueprint for repeated customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -685.29129224721, "y": 179.1294494367 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": -220 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -400, "y": 180 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "setNode", "position": { "x": -100, "y": 40 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.personalData.customer_id}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 160, "y": 40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": -80, "y": 260 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Loan creation declined", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "regex_match", "value": "^(Registration declined by CSAS|Request declined by CSAS)$", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "Registrator", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "is_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "wrong_person_code", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 190, "y": 260 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-8", "type": "waitNode", "position": { "x": -140, "y": 430 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-5", "type": "breakerNode", "position": { "x": -400, "y": 430 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -380, "y": -220 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/creditLine/application", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "_method", "value": "post" }, { "key": "apiLoan", "value": "cz" }, { "key": "paydays", "value": "{created_date}" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "{data_requested_amount}" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": -80, "y": -320 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 180, "y": -320 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -60, "y": -120 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 190, "y": -120 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -500, "y": -220 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{created_date}", "fields": [ { "source": "{created_date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+30 days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "Y-m-d" } ] } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-8-1-2", "source": "1-8", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.info}", "operator": "contains", "output": "Loan creation was approved", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "Klient", "output2": "" }, { "value": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "regex_not_match", "output": "^CSAS Evaluation is in progress$", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"info\"\\s*:\\s*\"[^\"]*Loan creation was approved)(?=.*\"addinfo\"\\s*:\\s*\"Klient\")(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))", "output2": "" } ] } }, { "id": "edge-1-2-1-5", "source": "1-2", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "pending", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "CSAS Evaluation is in progress", "output2": "" } ] } }, { "id": "edge-1-3-1-6", "source": "1-3", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-8", "source": "1-5", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "\"status\"\\s*:", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?s)(?=.*\"status\"\\s*:\\s*200)(?=.*\"data\"\\s*:\\s*\\{[^}]*\"status\"\\s*:\\s*\"success\")(?=.*\"credit_id\"\\s*:\\s*\"[^\"]+\")(?=.*\"url\"\\s*:\\s*\"[^\"]+\")", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Rerum is using CreditOnline platform with three client flows: new clients, registered clients and repeated clients. New clients are registered before the credit-line application; registered and repeated clients use the customer_id from Ping and apply directly. Like Tando, the check can return CSAS Evaluation is in progress. The current blueprints treat that as pending and retry behind a Wait + Breaker rather than rejecting it. What will be needed from advertiser Key Purpose endpoint CreditOnline tenant API base URL. token Application API key sent as apiKey. username RPC login. password RPC password. partner_id Broker identifier sent as brokerId. Flows New clients — Ping, checkPersonalData; success means all four checked identity fields are notFound. New clients — Post, transform data → registerClient → store customer_id → creditLine/application. Registered clients — Ping, success requires info containing Loan creation was approved, addinfo: Registrator, and customer_id. Post applies directly. Repeated clients — Ping, the same, but addinfo: Klient. Post applies directly. Calls POST {endpoint}/?RPC=agents.checkPersonalData POST {endpoint}/?RPC=agents.registerClient # new clients only POST {endpoint}/api/v1.0/creditLine/application?… The RPC calls use format: login-data-pass with Content-Type: application/x-www-form-urlencoded; charset=UTF-8. Their form body has three top-level keys: login, pass and data; the advertiser payload is written as data.* fields. login is {username} and pass is {password}. Do not build the envelope manually. The creditLine/application request is a plain query-string POST using {token} as apiKey and {partner_id} as brokerId. Response model checkPersonalData normally returns HTTP 200 for both positive and negative business decisions. The Ping must therefore read ok and personalData; HTTP status alone is not enough. The identity fields carry states such as notFound/registered, while info, addinfo and an optional customer_id describe the Rerum customer state. New clients accept the all-notFound case. Registered clients require info containing Loan creation was approved, addinfo: Registrator and customer_id; repeated clients require the same approval with addinfo: Klient. CSAS Evaluation is in progress is pending, not rejected. The current blueprints wait and retry it behind a breaker. Authentication can also fail inside an HTTP-200 RPC response with an err payload and no usable ok/personalData; that is a technical credentials failure, not a business rejection. New clients call registerClient only for a genuinely new person. Success supplies the customer_id for the application. Registration failures use err; only explicit business errors represented by the current branches should be mapped, while unrecognised/technical responses remain errors. Registered and repeated clients skip registration because Ping already returned the customer ID. The creditLine/application response contains a top-level status and nested data. The current Rerum success branch requires HTTP 200, top-level status: 200, data.status: success, a non-empty credit_id and a non-empty data.url. Request fields Ping Field Required Value realname yes {g_name_first} surname yes {g_name_last} email yes {g_email} mob_phone yes {g_phone} person_code yes {g_id_national_number} id_number yes {g_id_card_number} address yes {g_address_street} house yes {g_address_street_number} city yes {g_address_city} zipcode yes {g_address_zip} New clients — registration The current Post sends permanent and optional contact address fields plus income, costs, other_income, workplace, workplace_position, account_number, ip, amount, consent/declaration values and the contact-address flag. Empty contact/employer/job fields are omitted. Application Parameter Value customerId customer ID from registration or Ping amount {g_amount} maxAmount {g_amount} in the current blueprint paydays creation date + 30 days, Y-m-d account_number {g_bank_account_number}/{g_bank_account_code} brokerId {partner_id} apiLoan cz _method post apiKey {token} Transforms New clients map income types for registration: full-time → Zaměstnanec - plný pracovní úvazek, self-employed → OSVČ/Podnikatel, parental → Mateřská/Rodičovská, pension → Starobní/Invalidní důchodce, unemployed → Nezaměstnaný, other → Zaměstnanec - zkrácený pracovní úvazek. All Post variants derive paydays as created_date + 30 days formatted Y-m-d. The current Rerum blueprints do not cap the requested amount before the application. Outcomes Variant Recognised by Meaning Reject reason New clients Ping all four identity fields notFound New customer Registered clients Ping info ~ Loan creation was approved, addinfo: Registrator, customer_id Correct registered clients flow Repeated clients Ping same, addinfo: Klient Correct repeated clients flow any Ping addinfo: CSAS Evaluation is in progress Pending, retry addinfo: Registrator or Klient in the wrong client flow Known client / wrong client flow Duplicate addinfo: Registration declined by CSAS or Request declined by CSAS Scoring refusal Poor Credit addinfo: Loan creation declined Refused without specific reason Unspecified empty addinfo in the registered or repeated clients flow Wrong customer state Product Mismatch person_code: wrong_person_code Invalid national ID Invalid Data New clients Create: ok: 1 + customer_id Client registered Application: status: 200, data.status: success, credit_id, url Accepted recognised HTTP-200 non-success Create/Post Business refusal Unspecified Reject nodes store raw {body} in {reason_detail}. Technical non-200 responses are not mapped as business rejections. Branching New clients Ping accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.person_code} equals notFound {parsedBody.personalData.email} equals notFound {parsedBody.personalData.mob_phone} equals notFound {parsedBody.personalData.id_number} equals notFound Registered clients Ping accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.info} contains Loan creation was approved {parsedBody.personalData.addinfo} equals Registrator {parsedBody.personalData.customer_id} is not empty Repeated clients are identical except addinfo equals Klient. Application accepted: {status} equals 200 {parsedBody.status} equals 200 {parsedBody.data.status} equals success {parsedBody.data.credit_id} is not empty {parsedBody.data.url} is not empty Stored values Parameter Source {external_id} before application customer_id from Ping or registration {external_id} after application {parsedBody.data.credit_id} {redirect_url} {parsedBody.data.url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Švýcarská půjčka (CZ) Advertiser Švýcarská půjčka Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -700, "y": 120 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -641.67311225916, "y": 557.38834831011 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "setNode", "position": { "x": -540, "y": 60 }, "data": { "formData": { "active": true, "title": "Auth", "subtitle": "", "fields": [ { "key": "{auth0}", "value": "{username}:{password}" } ] } } }, { "id": "1-3", "type": "modifyFieldNode", "position": { "x": -380, "y": 120 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{auth}", "fields": [ { "source": "{auth0}", "operator": "always", "value": "", "value2": "", "modification": "to_base64", "pattern": "", "output": "" } ] }, { "fieldName": "{data_company_number_imported}", "fields": [ { "source": "{data_company_number_imported}", "operator": "regex_match", "value": "^(?!\\d{8}$).*$", "value2": "", "modification": "replace", "pattern": "", "output": " " } ] } ] } } }, { "id": "1-4", "type": "httpNode", "position": { "x": -200, "y": 120 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/api/lead/pre-check", "timeout": 15, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Authorization", "value": "Basic {auth}" } ], "query": [ { "key": "birthNumber", "value": "{data_nin}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-5", "type": "endNode", "position": { "x": 60, "y": 40 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-6", "type": "modifyFieldNode", "position": { "x": 20, "y": 160 }, "data": { "formData": { "active": true, "title": "Reject reason · No interest", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.state}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.state}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "pre-check: {parsedBody.state}" } ] } ] } } }, { "id": "1-7", "type": "modifyFieldNode", "position": { "x": 20, "y": 300 }, "data": { "formData": { "active": true, "title": "Reject reason · Invalid input", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{status}", "operator": "equals", "value": "400", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "18 let", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}" }, { "source": "{parsedBody.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.message}" } ] } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": 280, "y": 230 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -282.05173015128, "y": 542.58898873408 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "employed" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "self-employed" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "maternity" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "pensioner" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "unemployed" }, { "source": "{data_income_type}", "operator": "regex_not_match", "value": "^(full-time|self-employed|parental|pension|unemployed)$", "value2": "", "modification": "replace", "pattern": "", "output": "other" } ] }, { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "20000", "value2": "", "modification": "replace", "pattern": "", "output": "20000" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -20, "y": 560 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/lead", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Basic {auth}" } ], "query": [], "body": [ { "key": "sourceId", "value": "{eid}" }, { "key": "client.mail", "value": "{data_email}" }, { "key": "client.phone", "value": "{data_cell_phone}" }, { "key": "client.lastName", "value": "{data_last_name}" }, { "key": "client.firstName", "value": "{data_first_name}" }, { "key": "client.work.type", "value": "{data_income_type}" }, { "key": "loanRequest.days", "value": "{data_period}" }, { "key": "client.address.zip", "value": "{data_zip}" }, { "key": "client.birthNumber", "value": "{data_nin}" }, { "key": "loanRequest.amount", "value": "{data_requested_amount}" }, { "key": "client.address.city", "value": "{data_city}" }, { "key": "client.work.employer", "value": "{data_employer}" }, { "key": "loanRequest.currency", "value": "CZK" }, { "key": "client.address.number", "value": "{data_house_number}" }, { "key": "client.address.street", "value": "{data_street}" }, { "key": "client.identityNumber", "value": "{data_identity_card_number}" }, { "key": "client.work.businessId", "value": "{data_company_number_imported}" }, { "key": "client.cashFlows.income", "value": "{data_monthly_income}" }, { "key": "client.work.additionInfo", "value": "{data_job_title}" }, { "key": "client.cashFlows.expenses", "value": "{data_expenses}" }, { "key": "client.cashFlows.repaymentsLongLoans", "value": "0" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": 240, "y": 460 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.leadId}" }, { "key": "{redirect_url}", "value": "{parsedBody.loanCreateUrl}" } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 470, "y": 460 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": 240, "y": 600 }, "data": { "formData": { "active": true, "title": "Reject reason · No offer", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.state}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.state}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "state: {parsedBody.state}, no loanCreateUrl" } ] } ] } } }, { "id": "2-6", "type": "modifyFieldNode", "position": { "x": 240, "y": 750 }, "data": { "formData": { "active": true, "title": "Reject reason · Bad request", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.message}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "18 let", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.message}", "operator": "contains", "value": "duplic", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.message}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.message}" } ] } ] } } }, { "id": "2-8", "type": "endNode", "position": { "x": 520, "y": 750 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-5", "source": "1-4", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "lead", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.state}", "operator": "equals", "output": "lead", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "no-interest", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.state}", "operator": "regex_not_match", "output": "^lead$", "output2": "" } ] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "http error", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "regex_not_match", "output": "^200$", "output2": "" } ] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-8", "source": "1-7", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.loanCreateUrl}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "no-interest", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.loanCreateUrl}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-6", "source": "2-3", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "400 bad request", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "400", "output2": "" } ] } }, { "id": "edge-2-4-2-7", "source": "2-4", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-8", "source": "2-5", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-8", "source": "2-6", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Short-term loans. The ping is a genuine pre-check that stores nothing, which makes itcheap to call and honest to trust: if it says no, the post will say no too. Expect most leads to be refused at the ping, almost always with the same flatno-interest and no reason attached. Flows Ping, GET /api/lead/pre-check?birthNumber=…. Nothing is stored on the advertiser’sside. Returns state: lead or state: no-interest. Post, POST /api/lead with the full payload. Returns leadId, state andloanCreateUrl. The URL is present only when the advertiser is interested, and thepost can still come back no-interest even after the ping said lead, the pre-checkruns on fewer data. Calls Ping GET {endpoint}/api/lead/pre-check?birthNumber={g_id_national_number} Authorization: Basic base64({username}:{password}) Post POST {endpoint}/api/lead Authorization: Basic base64({username}:{password}) Content-Type: application/json format: application/json Basic auth is built in the blueprint from the two halves. Store {username} and {password} separately and encode at run time: Set {auth0} = {username}:{password} Modify {auth} ← {auth0}, to_base64 HTTP Authorization: Basic {auth} Never store a pre-encoded blob in {token}, it cannot be rotated one half at a time and nobody can read it six months later. Request fields The body uses dotted paths for nesting. Field Required Value sourceId yes {send_id} client.firstName yes {g_name_first} client.lastName yes {g_name_last} client.birthNumber yes {g_id_national_number} client.identityNumber yes {g_id_card_number} client.mail yes {g_email} client.phone yes {g_phone} client.address.street yes {g_address_street} client.address.number yes {g_address_street_number} client.address.city yes {g_address_city} client.address.zip yes {g_address_zip} client.work.type yes {g_fin_type}, see enums client.work.employer no {g_employer_name} client.work.businessId self-employed {g_company_registration} client.work.additionInfo no {g_employ_position} client.cashFlows.income yes {g_fin_income} client.cashFlows.expenses yes {g_fin_expenses} client.cashFlows.repaymentsLongLoans yes {g_fin_expenses_credit} loanRequest.amount yes {g_amount}, capped at 20 000 loanRequest.days yes {g_period} loanRequest.currency yes CZK client.identityNumber is validated hard: it must be at most ten characters and pass achecksum. It is the single most common 400. client.work.businessId must be exactly eight digits or absent. Anything else isrejected, so blank it when it does not match rather than passing a partial value through. On capping the amount Where a request exceeds the advertiser’s maximum, send the maximum rather than therequested figure, but agree it with them first. Translating a higher request down is rightonly when they would otherwise reject the lead outright. Where they would have made asmaller offer on their own, send what the applicant actually asked for and let them answer. This is the one place the general rule bends: amount, term and product are the requestitself, so they are normally passed through untouched. Enums client.work.type: employed, self-employed, maternity, pensioner, unemployed,other. Map anything unrecognised to other. Outcomes loanCreateUrl is nullable and it is the real signal. A 200 carrying state: rejectedor state: no-interest with a null URL is a rejection, whatever the status code says. Recognised by HTTP Meaning Reject reason Frequency state: lead 200 Interested, proceed , common loanCreateUrl not empty 200 Accepted , common state: no-interest 200 Not interested, no reason given Unspecified common state: rejected, null URL 200 Refused after full data Unspecified occasional message ~ číslo občanského průkazu 400 Invalid ID card number Invalid Data occasional message ~ rodné číslo 400 Invalid national ID Invalid Data rare message ~ nedovršil věk 18 let 400 Under eighteen Age rare The 400 body is {"code": …, "message": "(Tělo požadavku) client.identityNumber: …"}.The message names the field that failed and is worth passing through whole in{reason_detail}. no-interest is the largest single bucket and it says nothing. It is Unspecified, notNot Eligible, the advertiser has refused without naming a condition, and keeping it asUnspecified is what lets you go back and ask for reason codes. Reject reasons come from the standard list. See Reject reason for what each onemeans and when to use it. Branching Ping, interested: {status} equals 200 {parsedBody.state} equals lead Ping, not interested, scoped to the body, not to the status code: {status} equals 200 {parsedBody.state} regex not match ^lead$ Post, accepted: {status} equals 200 {parsedBody.loanCreateUrl} is not empty Post, refused: {status} equals 200 {parsedBody.loanCreateUrl} is empty Post, bad request: {status} equals 400 The 400 carries a documented business result naming the failed field, which is why itgets a branch. Other status codes do not. Stored values Parameter Source {external_id} {parsedBody.leadId} from the post {redirect_url} {parsedBody.loanCreateUrl} from the post Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Tando (CZ) Advertiser Tando Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Platform CreditOnline Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint Blueprint for new customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -980, "y": -80 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -980, "y": 430 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -760, "y": -80 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "30000", "value2": "", "modification": "replace", "pattern": "", "output": "30000" } ] }, { "fieldName": "{created_date}", "fields": [ { "source": "{created_date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+30 days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "Y-m-d" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "regex_match", "value": "^(Zaměstnanec - plný pracovní úvazek|Nezaměstnaný|OSVČ|Mateřská / Rodičovská|Důchodce)$", "value2": "", "modification": "replace", "pattern": "", "output": "{data_income_type}" }, { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "Zaměstnanec - plný pracovní úvazek" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "Nezaměstnaný" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "OSVČ" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "Mateřská / Rodičovská" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "Důchodce" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" }, { "source": "{data_income_type}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_employer}", "fields": [ { "source": "{data_employer}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_job_title}", "fields": [ { "source": "{data_job_title}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -530, "y": -80 }, "data": { "formData": { "active": true, "title": "Create", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.registerClient", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.ip", "value": "{ip_address}" }, { "key": "data.ref", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.costs", "value": "{data_expenses}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.amount", "value": "{data_requested_amount}" }, { "key": "data.income", "value": "{data_monthly_income}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.marketing", "value": "0" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.workplace", "value": "{data_employer}" }, { "key": "data.contract_c", "value": "1" }, { "key": "data.person_code", "value": "{data_nin}" }, { "key": "data.other_income", "value": "{data_income_type}" }, { "key": "data.chk9_formular", "value": " " }, { "key": "data.account_number", "value": "{data_account_number}/{data_bank_code}" }, { "key": "data.address_different", "value": "0" }, { "key": "data.chk10_vop_smlouva", "value": "Potvrzuji, že jsem si přečetl(a) a souhlasím s VOP a podmínkami smlouvy o úvěru" }, { "key": "data.workplace_position", "value": "{data_job_title}" }, { "key": "data.chk11_politicky_ex_osoba", "value": "Prohlašuji, že nejsem politicky exponovanou osobou a mnou uvedené informace jsou pravdivé" }, { "key": "data.chk12_osobni_udaje_registry", "value": "Souhlasím se zpracováním mých osobních údajů pro úvěrové registry" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "httpNode", "position": { "x": -120, "y": -120 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/creditLine/application", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "_method", "value": "post" }, { "key": "apiLoan", "value": "cz" }, { "key": "paydays", "value": "{created_date}" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "{data_requested_amount}" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-6", "type": "setNode", "position": { "x": 180, "y": -120 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "1-9", "type": "endNode", "position": { "x": 440, "y": -120 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": -315, "y": 100 }, "data": { "formData": { "active": true, "title": "Reject reason · Create", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.err}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Already registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Already registered or invalid", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Age check failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "Nesprávný formát", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.err}", "operator": "contains", "value": "JSON error", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": -35, "y": 100 }, "data": { "formData": { "active": true, "title": "Rejected · Create", "subtitle": "", "success": "failed" } } }, { "id": "1-7", "type": "modifyFieldNode", "position": { "x": 180, "y": 80 }, "data": { "formData": { "active": true, "title": "Reject reason · Post", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-10", "type": "endNode", "position": { "x": 440, "y": 80 }, "data": { "formData": { "active": true, "title": "Rejected · Post", "subtitle": "", "success": "failed" } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -700, "y": 430 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "endNode", "position": { "x": -230, "y": 320 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -230, "y": 500 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.email}", "operator": "equals", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.mob_phone}", "operator": "equals", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.id_number}", "operator": "equals", "value": "registered", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.addinfo}", "operator": "equals", "value": "C_Loan", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "wrong_person_code", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 60, "y": 500 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-6", "type": "breakerNode", "position": { "x": -498.80661577608, "y": 699.40203562341 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "2-8", "type": "waitNode", "position": { "x": -355.45547073791, "y": 633.8320610687 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "1-11", "type": "setNode", "position": { "x": -345, "y": -120 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.customer_id}" } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?=.*\"ok\"\\s*:\\s*1)(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?=.*\"status\"\\s*:\\s*200)(?=.*\"data\"\\s*:\\s*\\{)(?=.*\"status\"\\s*:\\s*\"success\")(?=.*\"credit_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))(?=.*\"url\"\\s*:\\s*\"[^\"]+\")", "output2": "" } ] } }, { "id": "edge-1-6-1-9", "source": "1-6", "target": "1-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-8", "source": "1-5", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-10", "source": "1-7", "target": "1-10", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-8-2-3", "source": "2-8", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "new customer", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.person_code}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.email}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.mob_phone}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.id_number}", "operator": "equals", "output": "notFound", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?=.*\"person_code\"\\s*:\\s*\"notFound\")(?=.*\"email\"\\s*:\\s*\"notFound\")(?=.*\"mob_phone\"\\s*:\\s*\"notFound\")(?=.*\"id_number\"\\s*:\\s*\"notFound\")(?!.*\"addinfo\"\\s*:\\s*\"[^\"]+\")(?=.*\"ok\"\\s*:\\s*1)", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "\"addinfo\"\\s*:\\s*\"CSAS Evaluation is in progress\"", "output2": "" } ] } }, { "id": "edge-2-3-2-6", "source": "2-3", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "pending", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "CSAS Evaluation is in progress", "output2": "" } ] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-8", "source": "2-6", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-11", "source": "1-3", "target": "1-11", "type": "customEdge", "data": { "active": true, "title": "registered", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-11-1-4", "source": "1-11", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-3", "source": "2-1", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Blueprint for repeated customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -900, "y": -60 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -900, "y": 430 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -680, "y": -60 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "30000", "value2": "", "modification": "replace", "pattern": "", "output": "30000" } ] }, { "fieldName": "{created_date}", "fields": [ { "source": "{created_date}", "operator": "always", "value": "", "value2": "", "modification": "modify_date", "pattern": "", "output": "+30 days" }, { "source": "{_1}", "operator": "always", "value": "", "value2": "", "modification": "format_date", "pattern": "", "output": "Y-m-d" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -430, "y": -60 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/v1.0/creditLine/application", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [ { "key": "amount", "value": "{data_requested_amount}" }, { "key": "apiKey", "value": "{token}" }, { "key": "_method", "value": "post" }, { "key": "apiLoan", "value": "cz" }, { "key": "paydays", "value": "{created_date}" }, { "key": "brokerId", "value": "{partner_id}" }, { "key": "maxAmount", "value": "{data_requested_amount}" }, { "key": "customerId", "value": "{external_id}" }, { "key": "account_number", "value": "{data_account_number}/{data_bank_code}" } ], "body": [], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": -130, "y": -100 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.data.url}" }, { "key": "{external_id}", "value": "{parsedBody.data.credit_id}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 140, "y": -100 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": -130, "y": 100 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 140, "y": 100 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -650, "y": 430 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/?RPC=agents.checkPersonalData", "timeout": 30, "format": "login-data-pass", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-type", "value": "application/x-www-form-urlencoded; charset=UTF-8" } ], "query": [], "body": [ { "key": "pass", "value": "{password}" }, { "key": "login", "value": "{username}" }, { "key": "data.city", "value": "{data_city}" }, { "key": "data.email", "value": "{data_email}" }, { "key": "data.house", "value": "{data_house_number}" }, { "key": "data.address", "value": "{data_street}" }, { "key": "data.surname", "value": "{data_last_name}" }, { "key": "data.zipcode", "value": "{data_zip}" }, { "key": "data.realname", "value": "{data_first_name}" }, { "key": "data.id_number", "value": "{data_identity_card_number}" }, { "key": "data.mob_phone", "value": "{data_cell_phone}" }, { "key": "data.person_code", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": -150, "y": 320 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.personalData.customer_id}" } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 120, "y": 320 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": -150, "y": 500 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "notFound", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "age_check_failed", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.personalData.person_code}", "operator": "equals", "value": "wrong_person_code", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "2-8", "type": "endNode", "position": { "x": 140, "y": 500 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-6", "type": "breakerNode", "position": { "x": -339.84160667145, "y": 707.79332449237 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "2-9", "type": "waitNode", "position": { "x": -204.29954528635, "y": 641.7438107868 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "accepted", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.data.status}", "operator": "equals", "output": "success", "output2": "" }, { "value": "{parsedBody.data.credit_id}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.data.url}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?=.*\"status\"\\s*:\\s*200)(?=.*\"data\"\\s*:\\s*\\{)(?=.*\"status\"\\s*:\\s*\"success\")(?=.*\"credit_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))(?=.*\"url\"\\s*:\\s*\"[^\"]+\")", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-9-2-3", "source": "2-9", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "eligible existing customer", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "C_Loan", "output2": "" }, { "value": "{parsedBody.personalData.customer_id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "rejected", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "(?=.*\"addinfo\"\\s*:\\s*\"C_Loan\")(?=.*\"customer_id\"\\s*:\\s*(?:\"[^\"]+\"|\\d+))(?=.*\"ok\"\\s*:\\s*1)", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "\"addinfo\"\\s*:\\s*\"CSAS Evaluation is in progress\"", "output2": "" } ] } }, { "id": "edge-2-3-2-6", "source": "2-3", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "pending", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.ok}", "operator": "equals", "output": "1", "output2": "" }, { "value": "{parsedBody.personalData.addinfo}", "operator": "equals", "output": "CSAS Evaluation is in progress", "output2": "" } ] } }, { "id": "edge-2-4-2-7", "source": "2-4", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-8", "source": "2-5", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-9", "source": "2-6", "target": "2-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-3", "source": "2-1", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Tando uses the CreditOnline backend and is split into two client flows: new clients for genuinely new customers and repeated clients for an existing customer marked C_Loan. Both use the same creditLine/application endpoint after a successful Ping; only new clients run registerClient first. The API can return CSAS Evaluation is in progress during Ping. That is not a rejection: both client flows wait and retry behind a Breaker. What will be needed from advertiser Key Purpose endpoint CreditOnline tenant API base URL. token Application API key sent as apiKey. username RPC login. password RPC password. partner_id Broker identifier sent as brokerId. Flows New clients — Ping, checkPersonalData. Success means all four checked identity fields are notFound and addinfo is empty. New clients — Post, transform data → registerClient → store customer_id → creditLine/application. Repeated clients — Ping, checkPersonalData. Success means addinfo: C_Loan and a non-empty customer_id. Repeated clients — Post, transform amount/date → creditLine/application directly with the customer ID from Ping. Calls POST {endpoint}/?RPC=agents.checkPersonalData POST {endpoint}/?RPC=agents.registerClient # new clients only POST {endpoint}/api/v1.0/creditLine/application?… The RPC calls use format: login-data-pass with Content-Type: application/x-www-form-urlencoded; charset=UTF-8. Their form body has three top-level keys: login, pass and data, with the advertiser payload written as data.* fields. login is {username} and pass is {password}. Do not build the form by hand. The creditLine/application call is a plain query-string POST using {token} as apiKey and {partner_id} as brokerId. Response model checkPersonalData answers with HTTP 200 for normal business decisions, including refusals, so the Ping decision is always made from ok and personalData. Identity fields are returned as states such as notFound/registered; addinfo carries the customer state used by Tando. New clients accept only an all-notFound client with empty addinfo; repeated clients accept addinfo: C_Loan with a customer_id. CSAS Evaluation is in progress is a temporary state and is retried rather than rejected. An authentication failure may also arrive as HTTP 200 with an err payload and no usable ok/personalData. That is technical and must not be interpreted as either a successful Ping or a business rejection. New clients call registerClient only after the Ping. A successful registration provides the customer_id used by the application. Any URL returned by registration is not the application conversion URL. Registration failures use err; the current blueprint maps only the concrete messages shown under Outcomes. Repeated clients skip registration because Ping already supplied customer_id. creditLine/application returns a top-level status plus nested data. The current Tando success branch is deliberately stricter than CreditGO: it requires HTTP 200, top-level status: 200, nested data.status: success, a non-empty credit_id and a non-empty data.url. Request fields Ping Field Required Value realname yes {g_name_first} surname yes {g_name_last} email yes {g_email} mob_phone yes {g_phone} person_code yes {g_id_national_number} id_number yes {g_id_card_number} address yes {g_address_street} house yes {g_address_street_number} city yes {g_address_city} zipcode yes {g_address_zip} New clients — registration The current blueprint sends the same identity/address data plus income, costs, other_income, workplace, workplace_position, account_number, ip, consent/declaration fields, and amount. Empty employer and job-title values are omitted. Application Parameter Value customerId customer ID from registration or Ping amount capped {g_amount}, max 30000 maxAmount the same capped amount paydays due date = creation date + 30 days, Y-m-d account_number {g_bank_account_number}/{g_bank_account_code} brokerId {partner_id} apiLoan cz _method post apiKey {token} Transforms Both Post variants cap the amount at 30000 and derive paydays as created_date + 30 days formatted Y-m-d. New clients additionally translate income types for registration: full-time → Zaměstnanec - plný pracovní úvazek, unemployed → Nezaměstnaný, self-employed → OSVČ, parental → Mateřská / Rodičovská, pension → Důchodce. other and an empty value are not sent as other_income. Outcomes Variant Recognised by Meaning Reject reason New clients Ping all four identity fields notFound, empty addinfo New customer Repeated clients Ping addinfo: C_Loan + customer_id Eligible existing customer either Ping addinfo: CSAS Evaluation is in progress Pending, wait and retry Ping reject any checked identity field registered / C_Loan in the new clients flow Already known Existing Customer Ping reject person_code: age_check_failed Age check failed Age Ping reject person_code: wrong_person_code Invalid national ID Invalid Data Repeated clients Ping reject person_code: notFound Wrong customer state for repeated clients Product Mismatch New clients Create ok: 1 + non-empty customer_id Client registered New clients Create err ~ Already registered Existing customer Existing Customer New clients Create err ~ Age check failed Age check failed Age New clients Create err ~ Nesprávný formát or JSON error Invalid payload Invalid Data Application HTTP 200, top-level status: 200, data.status: success, non-empty credit_id and url Accepted recognised HTTP-200 non-success application Refused Unspecified {reason_detail} is always the raw {body} on reject nodes. Branching New clients Ping accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.person_code} equals notFound {parsedBody.personalData.email} equals notFound {parsedBody.personalData.mob_phone} equals notFound {parsedBody.personalData.id_number} equals notFound {parsedBody.personalData.addinfo} is empty Repeated clients Ping accepted: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.addinfo} equals C_Loan {parsedBody.personalData.customer_id} is not empty Pending: {status} equals 200 {parsedBody.ok} equals 1 {parsedBody.personalData.addinfo} equals CSAS Evaluation is in progress Application accepted: {status} equals 200 {parsedBody.status} equals 200 {parsedBody.data.status} equals success {parsedBody.data.credit_id} is not empty {parsedBody.data.url} is not empty Stored values Parameter Source {external_id} before application customer_id from Ping or registration {external_id} after application {parsedBody.data.credit_id} {redirect_url} {parsedBody.data.url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Úvěráček (CZ) Advertiser Úvěráček Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 420 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -620, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "httpNode", "position": { "x": -210, "y": 420 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "PUT", "endpoint": "{endpoint}/api/v1/uveracek-cpl/pre-check", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Accept", "value": "application/json" } ], "query": [ { "key": "apiKey", "value": "{token}" } ], "body": [ { "key": "lastName", "value": "{data_last_name}" }, { "key": "firstName", "value": "{data_first_name}" }, { "key": "birthNumber", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-3", "type": "setNode", "position": { "x": 40, "y": 360 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{custom_process_id}", "value": "{parsedBody.processId}" } ] } } }, { "id": "1-5", "type": "endNode", "position": { "x": 280, "y": 360 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": 40, "y": 520 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "REJECTED", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "pre-check http {status}: {parsedBody.status}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 300, "y": 520 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "modifyFieldNode", "position": { "x": -430, "y": -20 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "ENTREPRENEUR" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "RETIREE" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "regex_not_match", "value": "^(full-time|self-employed|parental|pension|unemployed|other)$", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{own_property}", "fields": [ { "source": "{data_own_property}", "operator": "equals", "value": "yes", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_own_property}", "operator": "equals", "value": "no", "value2": "", "modification": "replace", "pattern": "", "output": "0" } ] } ] } } }, { "id": "2-3", "type": "httpNode", "position": { "x": -210, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "PUT", "endpoint": "{endpoint}/api/v1/uveracek-cpl/applicant", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Accept", "value": "application/json" } ], "query": [ { "key": "apiKey", "value": "{token}" } ], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "phone", "value": "{data_cell_phone}" }, { "key": "lastName", "value": "{data_last_name}" }, { "key": "firstName", "value": "{data_first_name}" }, { "key": "ipAddress", "value": "{ip_address}" }, { "key": "processId", "value": "{custom_process_id}" }, { "key": "incomeType", "value": "{income_type}" }, { "key": "loanAmount", "value": "{data_requested_amount}" }, { "key": "loanPeriod", "value": "{data_period}" }, { "key": "birthNumber", "value": "{data_nin}" }, { "key": "idCardNumber", "value": "{data_identity_card_number}" }, { "key": "childrenCount", "value": "0" }, { "key": "maritalStatus", "value": "SINGLE" }, { "key": "monthlyIncome", "value": "{data_monthly_income}" }, { "key": "propertyOwner", "value": "toBool({own_property})" }, { "key": "monthlyPayment", "value": "{data_expenses}" }, { "key": "dateOfAgreement", "value": "{created_date}" }, { "key": "contactAddress.zip", "value": "{data_contact_zip}" }, { "key": "contactAddress.city", "value": "{data_contact_city}" }, { "key": "permanentAddress.zip", "value": "{data_zip}" }, { "key": "contactAddress.street", "value": "{data_contact_street} {data_contact_house_number}" }, { "key": "permanentAddress.city", "value": "{data_city}" }, { "key": "permanentAddress.street", "value": "{data_street} {data_house_number}" } ], "signature": null, "insecure": null } } }, { "id": "2-4", "type": "setNode", "position": { "x": 40, "y": -20 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.redirectUrl}" }, { "key": "{external_id}", "value": "{parsedBody.refno}" } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 300, "y": -20 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-5", "type": "modifyFieldNode", "position": { "x": 40, "y": 140 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.message}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "UNSATISFACTORY", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{status}", "operator": "equals", "value": "400", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "DUPLICITY", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{status}", "operator": "regex_match", "value": "^(403|500)$", "value2": "", "modification": "replace", "pattern": "", "output": "ERROR" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {parsedBody.message}" } ] } ] } } }, { "id": "2-7", "type": "endNode", "position": { "x": 300, "y": 140 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "PASSED", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "regex_match", "output": "PASSED", "output2": "" } ] } }, { "id": "edge-1-2-1-4", "source": "1-2", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "not PASSED", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "regex_not_match", "output": "PASSED", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "OK", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "equals", "output": "OK", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "!OK", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "not_equals", "output": "OK", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Both calls are PUT, and the API key travels as a query parameter. The pattern to know here: 400 is a business answer, not a fault. The advertiser says “this applicant does not meet the criteria” by returning 400 with UNSATISFACTORY in the body. Treating it as a technical error throws away a mapped rejection. What will be needed from advertiser Key Purpose endpoint Base API URL. token API key sent as apiKey. Flows Ping, PUT /api/v1/uveracek-cpl/pre-check. Name and national ID only. Returns a processId when it passes. Post, PUT /api/v1/uveracek-cpl/applicant. Full payload, carrying the processId from the ping. Returns refno and redirectUrl. The processId is what links the two calls. It is a working value, not the advertiser’s lasting reference, so it goes in a custom_ parameter, refno is what becomes {external_id}. Calls PUT {endpoint}/api/v1/uveracek-cpl/pre-check?apiKey={token} PUT {endpoint}/api/v1/uveracek-cpl/applicant?apiKey={token} Accept: application/json format: application/json Request fields Ping Field Required Value firstName yes {g_name_first} lastName yes {g_name_last} birthNumber yes {g_id_national_number} Post Field Required Value processId yes {custom_process_id} from the ping firstName yes {g_name_first} lastName yes {g_name_last} birthNumber yes {g_id_national_number} idCardNumber yes {g_id_card_number} email yes {g_email} phone yes {g_phone} permanentAddress.street yes {g_address_street} {g_address_street_number} permanentAddress.city yes {g_address_city} permanentAddress.zip yes {g_address_zip} contactAddress.street yes {g_address_contact_street} {g_address_contact_street_number} contactAddress.city yes {g_address_contact_city} contactAddress.zip yes {g_address_contact_zip} loanAmount yes {g_amount} loanPeriod yes {g_period} monthlyIncome yes {g_fin_income} monthlyPayment yes {g_fin_expenses} incomeType yes {g_fin_type}, see enums maritalStatus yes {g_marital_status}, see enums childrenCount yes {g_household_children} propertyOwner yes toBool(...) dateOfAgreement yes {created_date} ipAddress yes {ip_address} Compose street and house number in the HTTP field. It is not a transformation. Enums incomeType: EMPLOYEE, ENTREPRENEUR, RETIREE, OTHER. Maternity, unemployment and anything else map to OTHER. maritalStatus: SINGLE, MARRIED, DIVORCED, WIDOWED. Outcomes Recognised by HTTP Meaning Reject reason Frequency status: PASSED + processId 200 Pre-check passed , common status: OK + refno 201 Accepted , occasional status: REJECTED 200 Pre-check refused, no reason given Unspecified common status: UNSATISFACTORY 400 Does not meet the criteria Not Eligible common status: DUPLICITY 400 Already on file Duplicate occasional message: UNSATISFACTORY 400 Same, without a status field Not Eligible occasional code: 500, status: error 500 Gateway or advertiser failure , (technical) rare UNSATISFACTORY names a condition, insufficient income, insolvency, a knockout the lead failed, so it is Not Eligible. The pre-check’s bare REJECTED names nothing and is Unspecified. The distinction matters: Unspecified is a bill you can present to the advertiser, Not Eligible reads as a reason already given and nobody asks again. Do not derive a reason from the 400 itself. 400 here can be either UNSATISFACTORY or DUPLICITY, and the body says which. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, passed: {parsedBody.status} regex match PASSED Ping, refused, a catch-all against the one known success value: {parsedBody.status} regex not match PASSED Post, accepted: {parsedBody.status} equals OK Post, refused: {parsedBody.status} not equals OK 403 and 500 carry no business result and get no branch, PalDock fills those in on its own. Stored values Parameter Source {custom_process_id} {parsedBody.processId} from the ping {external_id} {parsedBody.refno} from the post {redirect_url} {parsedBody.redirectUrl} from the post Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Úvěrová pokladna (CZ) Advertiser Úvěrová pokladna Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -560, "y": -160 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -560, "y": 200 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -400, "y": -160 }, "data": { "formData": { "active": true, "title": "Transform Data", "subtitle": "", "data": [ { "fieldName": "{housing_type}", "fields": [ { "source": "{data_home_status}", "operator": "regex_match", "value": "^(OwnHouse|InRent|Hostel|ByClosePerson|CooperativeHousing)$", "value2": "", "modification": "replace", "pattern": "", "output": "{data_home_status}" }, { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "OwnHouse" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "InRent" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "ByClosePerson" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "Hostel" } ] }, { "fieldName": "{income_source}", "fields": [ { "source": "{data_income_type}", "operator": "regex_match", "value": "^(FullEmployment|DisabilityPension|OwnAccountWorker|Pension|MaternityLeave|AgreementOnWorkActivity|Other)$", "value2": "", "modification": "replace", "pattern": "", "output": "{data_income_type}" }, { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "FullEmployment" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "OwnAccountWorker" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MaternityLeave" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "Pension" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "Other" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "Other" } ] }, { "fieldName": "{is_osvc}", "fields": [ { "source": "{data_income_type}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "0" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "1" }, { "source": "{data_income_type}", "operator": "equals", "value": "OwnAccountWorker", "value2": "", "modification": "replace", "pattern": "", "output": "1" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -240, "y": -160 }, "data": { "formData": { "active": true, "title": "Auth", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/leads/login-with-api-key", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "apiKey", "value": "{token}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": -80, "y": -160 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{access_token}", "value": "{parsedBody.result.token}" } ] } } }, { "id": "1-5", "type": "httpNode", "position": { "x": 80, "y": -160 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/leads/pre-check-sync/{data_nin}", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Bearer {access_token}" } ], "query": [], "body": [], "signature": null, "insecure": null } } }, { "id": "1-6", "type": "setNode", "position": { "x": 400, "y": -220 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{lead_precheck_id}", "value": "{parsedBody.result.id}" } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": 560, "y": -220 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-7", "type": "modifyFieldNode", "position": { "x": 400, "y": -80 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.result.accepted}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.result.errorMessage}", "operator": "regex_match", "value": "duplic", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.result.errorMessage}", "operator": "regex_match", "value": "(age|věk)", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.result.accepted}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "pre-check declined" }, { "source": "{parsedBody.result.errorMessage}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.result.errorMessage}" }, { "source": "{parsedBody.error.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.error.message}" } ] } ] } } }, { "id": "1-9", "type": "endNode", "position": { "x": 560, "y": -80 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -400, "y": 200 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/leads/import", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Bearer {access_token}" } ], "query": [], "body": [ { "key": "leads.0.expenses", "value": "toInt({data_expenses})" }, { "key": "leads.0.incomeNet", "value": "toInt({data_monthly_income})" }, { "key": "leads.0.ipAddress", "value": "{ip_address}" }, { "key": "leads.0.externalId", "value": "{eid}" }, { "key": "leads.0.loanAmount", "value": "toInt({data_requested_amount})" }, { "key": "leads.0.housingType", "value": "{housing_type}" }, { "key": "leads.0.employerName", "value": "{data_employer}" }, { "key": "leads.0.incomeSource", "value": "{income_source}" }, { "key": "leads.0.userLastName", "value": "{data_last_name}" }, { "key": "leads.0.daysToDueDate", "value": "toInt({data_period})" }, { "key": "leads.0.isLoanForOSVC", "value": "toBool({is_osvc})" }, { "key": "leads.0.propertyOwner", "value": "{data_own_property}" }, { "key": "leads.0.userFirstName", "value": "{data_first_name}" }, { "key": "leads.0.userPhoneNumber", "value": "{data_cell_phone}" }, { "key": "leads.0.userEmailAddress", "value": "{data_email}" }, { "key": "leads.0.bankAccountNumber", "value": "{data_account_number}" }, { "key": "leads.0.bankAccountBankCode", "value": "{data_bank_code}" }, { "key": "leads.0.permanentAddress.city", "value": "{data_city}" }, { "key": "leads.0.permanentAddress.street", "value": " {data_street} {data_house_number}" }, { "key": "leads.0.permanentAddress.zipCode", "value": "{data_zip}" }, { "key": "leads.0.identificationDocumentNumber", "value": "{data_identity_card_number}" }, { "key": "leads.0.personalIdentificationNumber", "value": "{data_nin}" }, { "key": "leads.0.ownAccountWorkerIdentificationNumber", "value": "{data_company_number_imported}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "setNode", "position": { "x": -240, "y": 140 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.result.leadIds.0.id}" }, { "key": "{redirect_url}", "value": "{parsedBody.result.leadIds.0.redirectUrl}" } ] } } }, { "id": "2-5", "type": "endNode", "position": { "x": -80, "y": 140 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-4", "type": "modifyFieldNode", "position": { "x": -240, "y": 280 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.result.leadIds.0.leadStatus}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.result.leadIds.0.leadStatus}", "operator": "equals", "value": "2", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.result.errors.0}", "operator": "regex_match", "value": "Duplicate record", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.result.errors.0}", "operator": "regex_match", "value": "(Invalid code|invalid format|not valid format|is required|max length)", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.result.errors.0}", "operator": "regex_match", "value": "nedostatečného příjmu", "value2": "", "modification": "replace", "pattern": "", "output": "Low Income" }, { "source": "{parsedBody.result.errors.0}", "operator": "regex_match", "value": "mimo definované hodiny", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.result.errors.0}", "operator": "regex_match", "value": "Půjčky pro fyzické osoby", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.result.leadIds.0.leadStatus}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "leadStatus={parsedBody.result.leadIds.0.leadStatus}" }, { "source": "{parsedBody.result.errors.0}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.result.errors.0}" }, { "source": "{parsedBody.error.message}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.error.message}" } ] } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": -80, "y": 280 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.result.isOk}", "operator": "equals", "output": "true", "output2": "" }, { "value": "{parsedBody.result.token}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-5", "source": "1-4", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-6", "source": "1-5", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.result.accepted}", "operator": "equals", "output": "true", "output2": "" } ] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.result.accepted}", "operator": "not_equals", "output": "true", "output2": "" }, { "value": "{status}", "operator": "is_less_than", "output": "400", "output2": "" } ] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-9", "source": "1-7", "target": "1-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.result.leadIds.0.leadStatus}", "operator": "equals", "output": "1", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.result.leadIds.0.leadStatus}", "operator": "not_equals", "output": "1", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details Bearer-token API. An API key is exchanged for a token, and the token authorises everything after it. The pre-check is synchronous and returns a plain yes or no; the import posts the lead. The responses are wrapped: the payload always sits under result, and the wrapper carries its own success and error alongside the HTTP status. What will be needed from advertiser Key Purpose endpoint Base API URL. token API key exchanged for the bearer token. Flows Ping, authenticate, then POST /api/leads/pre-check-sync/{national_id}. Returns result.accepted. Post, POST /api/leads/import with the lead. Returns a leadStatus code and, when accepted, a redirect URL. Authentication runs once per flow. The token stays valid for the calls that follow it, so a second Auth node before every request is duplication, not safety. The Post flow does authenticate again rather than reading a token the Ping stored, a token has a lifetime and the Post may run much later. Calls Auth POST {endpoint}/api/leads/login-with-api-key Content-Type: application/json format: application/json { "apiKey": "{token}" } Response: { "result": { "isOk": true, "token": "…", "errorMessage": null }, "success": true, "error": null, "targetUrl": null, "unAuthorizedRequest": false, "__abp": true } The token is at result.token. Reading it from anywhere else leaves the header empty, and every call after it comes back 401, a whole integration silently returning nothing but authentication failures, with no error anywhere in the run. Ping and Post POST {endpoint}/api/leads/pre-check-sync/{g_id_national_number} POST {endpoint}/api/leads/import Authorization: Bearer {custom_access_token} Content-Type: application/json format: application/json The advertiser restricts access by IP address; the addresses have to be registered with them first. Request fields The pre-check takes the national ID in the path and no body. The import sends an array with a single lead, so every field is prefixed leads.0.: Field Required Value leads.0.userFirstName yes {g_name_first} leads.0.userLastName yes {g_name_last} leads.0.personalIdentificationNumber yes {g_id_national_number} leads.0.identificationDocumentNumber yes {g_id_card_number} leads.0.userEmailAddress yes {g_email} leads.0.userPhoneNumber yes {g_phone} leads.0.permanentAddress.street yes {g_address_street} {g_address_street_number} leads.0.permanentAddress.city yes {g_address_city} leads.0.permanentAddress.zipCode yes {g_address_zip} leads.0.loanAmount yes toInt({g_amount}) leads.0.daysToDueDate yes toInt({g_period}) leads.0.incomeNet yes toInt({g_fin_income}) leads.0.expenses yes toInt({g_fin_expenses}) leads.0.incomeSource yes {g_fin_type}, see enums leads.0.housingType yes {g_home_type}, see enums leads.0.employerName no {g_employer_name} leads.0.isLoanForOSVC yes toBool(...), true for the self-employed leads.0.propertyOwner no {g_asset_status} leads.0.bankAccountNumber yes {g_bank_account_number} leads.0.bankAccountBankCode yes {g_bank_account_code} leads.0.ownAccountWorkerIdentificationNumber self-employed {g_company_registration} leads.0.externalId yes {send_id} leads.0.ipAddress yes {ip_address} Compose the street and number together in the HTTP field. That is not a transformation and does not need a Modify step. Numeric fields are typed, so convert inline with toInt(...) and toBool(...). One conversion, never nested. Enums incomeSource: FullEmployment, OwnAccountWorker, Pension, DisabilityPension, MaternityLeave, AgreementOnWorkActivity, Other. housingType: OwnHouse, InRent, Hostel, ByClosePerson, CooperativeHousing. isLoanForOSVC is derived rather than collected: it is true exactly when the income source is self-employment. Outcomes leadIds is an array even though only one lead was sent, so its values sit at result.leadIds.0..... Without the index the reference does not resolve. Recognised by Meaning Reject reason Frequency result.accepted: true Pre-check passed , common result.leadIds.0.leadStatus: 1 Accepted for processing , common result.accepted: false Pre-check refused, no reason given Unspecified common result.leadIds.0.leadStatus: 2 Failed the knockout lead scoring Not Eligible common result.errors.0 ~ Duplicate record Already on file Duplicate occasional result.errors.0 ~ `Invalid code invalid format is required max length` result.errors.0 ~ nedostatečného příjmu Income below threshold Low Income occasional result.errors.0 ~ mimo definované hodiny Outside accepted hours Outside Hours rare result.errors.0 ~ Půjčky pro fyzické osoby Wrong product for this applicant Product Mismatch rare result.errorMessage ~ duplic Already on file Duplicate rare result.errorMessage ~ age, věk Below the age limit Age rare leadStatus is a numeric code with its own meaning, and only some of it belongs in the run: Code Meaning Where it shows up 0 Unknown, should not occur , 1 Accepted after lead scoring at import 2 Refused by knockout lead scoring at import 3 Refused during later processing postback 4 Cancelled during later processing postback 5 Converted and commissionable postback Codes 3, 4 and 5 arrive later by postback and never appear in the response. They belong to the Tracking API, not to the integration. Branch only on 1 and 2. leadStatus: 2 is the one place in this integration where Not Eligible is right: the advertiser has named a knockout criterion the lead failed. A bare accepted: false at the pre-check names nothing and is Unspecified. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Auth succeeded: {parsedBody.result.isOk} equals true {parsedBody.result.token} is not empty Ping, accepted: {parsedBody.result.accepted} equals true Ping, refused, paired with a status test so that only the advertiser’s own answers reach it: {parsedBody.result.accepted} not equals true {status} is less than 400 Post, accepted: {parsedBody.result.leadIds.0.leadStatus} equals 1 Post, refused: {parsedBody.result.leadIds.0.leadStatus} not equals 1 Stored values Parameter Source {custom_access_token} {parsedBody.result.token} from Auth {custom_precheck_id} {parsedBody.result.id} from the pre-check {external_id} {parsedBody.result.leadIds.0.id} from the import {redirect_url} {parsedBody.result.leadIds.0.redirectUrl} from the import The access token is a working value with a lifetime, so it belongs in a custom_ parameter, not in {external_id} and not written back into the secrets table. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to ViaSMS (CZ) Advertiser ViaSMS Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -358.51408450704, "y": 228.49295774648 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -481.5, "y": -28.5 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -192.5, "y": 155.5 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_nin}", "fields": [ { "source": "{data_nin}", "operator": "always", "value": "", "value2": "", "modification": "regex_replace", "pattern": "(\\d{6})(\\d{3,4})", "output": "$1/$2" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYMENT" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYMENT" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "SOCIAL_OR_PARENTAL_SUPPORT" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -59.5, "y": 267.5 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/public/partners/{partner_id}/requests", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "X-Api-Key", "value": "{token}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "national_id", "value": "{data_nin}" }, { "key": "mobile_phone", "value": "{data_cell_phone}" }, { "key": "income_source", "value": "{data_income_type}" }, { "key": "living_expenses", "value": "{data_expenses}" }, { "key": "net_monthly_income", "value": "{data_monthly_income}" }, { "key": "requested_principal", "value": "{data_requested_amount}" }, { "key": "expenses_on_existing_loans", "value": "0" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 97.5, "y": 131.8125 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{external_id}", "value": "{parsedBody.request_uuid}" } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 293.50431757158, "y": 173.63153106718 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-4", "type": "httpNode", "position": { "x": -244.38893078905, "y": -287.39736298286 }, "data": { "formData": { "active": true, "title": "Status", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/api/public/partners/{partner_id}/requests/{external_id}", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "X-Api-Key", "value": "{token}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "national_id", "value": "{data_identity_card_number}" }, { "key": "mobile_phone", "value": "{data_cell_phone}" }, { "key": "income_source", "value": "{data_income_type}" }, { "key": "living_expenses", "value": "{data_expenses}" }, { "key": "net_monthly_income", "value": "{data_monthly_income}" }, { "key": "requested_principal", "value": "{data_requested_amount}" }, { "key": "expenses_on_existing_loans", "value": "0" } ], "signature": null, "insecure": null } } }, { "id": "2-10", "type": "setNode", "position": { "x": 302.53878619553, "y": -133.90663788756 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.redirect_url}" } ] } } }, { "id": "2-2", "type": "waitNode", "position": { "x": -280.83943177874, "y": 25.651915559501 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "2-5", "type": "httpNode", "position": { "x": -77.788471532623, "y": -139.3085673168 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/public/partners/{partner_id}/requests/{external_id}/accept", "timeout": 40, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "X-Api-Key", "value": "{token}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [], "signature": null, "insecure": null } } }, { "id": "2-9", "type": "httpNode", "position": { "x": 139.80261398431, "y": -31.44990073426 }, "data": { "formData": { "active": true, "title": "Status after accept", "subtitle": "", "method": "GET", "endpoint": "{endpoint}/api/public/partners/{partner_id}/requests/{external_id}", "timeout": 30, "format": null, "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "X-Api-Key", "value": "{token}" }, { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "national_id", "value": "{data_identity_card_number}" }, { "key": "mobile_phone", "value": "{data_cell_phone}" }, { "key": "income_source", "value": "{data_income_type}" }, { "key": "living_expenses", "value": "{data_expenses}" }, { "key": "net_monthly_income", "value": "{data_monthly_income}" }, { "key": "requested_principal", "value": "{data_requested_amount}" }, { "key": "expenses_on_existing_loans", "value": "0" } ], "signature": null, "insecure": null } } }, { "id": "2-7", "type": "waitNode", "position": { "x": 79.57147619086, "y": -201.75762736685 }, "data": { "formData": { "active": true, "title": "Wait 3s", "subtitle": "", "type": "delay", "delayValue": 3, "delayUnit": "seconds", "untilDate": null } } }, { "id": "2-12", "type": "endNode", "position": { "x": 513.8223081858, "y": -153.93392562595 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 91.082862387772, "y": 276.93279633276 }, "data": { "formData": { "active": true, "title": "Reject reason · Invalid field", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.field_errors.0.field_name}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.field_errors.0.field_name}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.field_errors.0.field_name}: {parsedBody.field_errors.0.error_message}" } ] } ] } } }, { "id": "2-6", "type": "modifyFieldNode", "position": { "x": -69.819893455799, "y": -298.07445834702 }, "data": { "formData": { "active": true, "title": "Reject reason · Status", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "equals", "value": "INVALID", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "FAILED", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "CANCELLED", "value2": "", "modification": "replace", "pattern": "", "output": "Cancelled by Advertiser" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "EXPIRED", "value2": "", "modification": "replace", "pattern": "", "output": "Expired" }, { "source": "{parsedBody.errors.0.error_code}", "operator": "equals", "value": "OPEN_LOAN_APPLICATION", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.status}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.status}" } ] } ] } } }, { "id": "2-3", "type": "breakerNode", "position": { "x": -400.09804338708, "y": -249.6716260295 }, "data": { "formData": { "active": true, "title": "Breaker 4x", "subtitle": "", "maxRepetition": "4" } } }, { "id": "1-8", "type": "endNode", "position": { "x": 270.14518454561, "y": 292.76661025696 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-8", "type": "endNode", "position": { "x": 189.97184058348, "y": -308.75155371118 }, "data": { "formData": { "active": true, "title": "Rejected · Status", "subtitle": "", "success": "failed" } } }, { "id": "2-11", "type": "modifyFieldNode", "position": { "x": 300.31941250167, "y": 23.662015292937 }, "data": { "formData": { "active": true, "title": "Reject reason · Status after accept", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "equals", "value": "INVALID", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "FAILED", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "CANCELLED", "value2": "", "modification": "replace", "pattern": "", "output": "Cancelled by Advertiser" }, { "source": "{parsedBody.status}", "operator": "equals", "value": "EXPIRED", "value2": "", "modification": "replace", "pattern": "", "output": "Expired" }, { "source": "{parsedBody.errors.0.error_code}", "operator": "equals", "value": "OPEN_LOAN_APPLICATION", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.status}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.status}" } ] } ] } } }, { "id": "2-13", "type": "endNode", "position": { "x": 497.03336978445, "y": 49.052374722548 }, "data": { "formData": { "active": true, "title": "Rejected · Status after accept", "subtitle": "", "success": "failed" } } }, { "id": "1-6", "type": "modifyFieldNode", "position": { "x": 63.881191692614, "y": 406.18286898936 }, "data": { "formData": { "active": true, "title": "Reject reason · Business error", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.errors.0.error_code}", "operator": "equals", "value": "OPEN_LOAN_APPLICATION", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{parsedBody.errors.0.error_code}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{parsedBody.errors.0.error_message}" } ] } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody.errors.0.error_code}", "operator": "is_empty", "output": "", "output2": "" }, { "value": "{parsedBody.field_errors.0.field_name}", "operator": "is_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.field_errors.0.field_name}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-6", "source": "1-3", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.errors.0.error_code}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-4-1-7", "source": "1-4", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-3-2-4", "source": "2-3", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-2", "source": "2-4", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "equals", "output": "NEW", "output2": "" } ] } }, { "id": "edge-2-4-2-5", "source": "2-4", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "equals", "output": "LOAN_OFFER_GENERATED", "output2": "" } ] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{2-4.parsedBody.status}", "operator": "regex_match", "output": "INVALID|CANCELLED|FAILED|EXPIRED", "output2": "" } ] } }, { "id": "edge-2-9-2-10", "source": "2-9", "target": "2-10", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{parsedBody.status}", "operator": "regex_match", "output": "ACCEPTED|COMPLETED|LOAN_ISSUED", "output2": "" } ] } }, { "id": "edge-2-10-2-12", "source": "2-10", "target": "2-12", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-5-2-7", "source": "2-5", "target": "2-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-7-2-9", "source": "2-7", "target": "2-9", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-9-2-11", "source": "2-9", "target": "2-11", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{2-9.parsedBody.status}", "operator": "regex_match", "output": "INVALID|CANCELLED|FAILED|EXPIRED", "output2": "" } ] } }, { "id": "edge-1-5-1-8", "source": "1-5", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-6-2-8", "source": "2-6", "target": "2-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-6-1-8", "source": "1-6", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-11-2-13", "source": "2-11", "target": "2-13", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details An asynchronous, state-machine API. The application request returns immediately with status: NEW; the offer is generated a few seconds later. Nothing is decided in the first response, so the integration has to poll. Two things shape every decision here: HTTP 200 does not mean accepted, and an application left open blocks the next lead from the same person. What will be needed from advertiser Key Purpose endpoint Base API URL. token API key sent in X-Api-Key. partner_id Partner ID used in the request path. Flows Ping, POST /requests. Submits the application. Returns request_uuid and status: NEW, or a rejection in the body under 200. Post, polls GET /requests/{request_uuid} until the status is terminal, then POST /requests/{request_uuid}/accept, then polls again. The request_uuid from the ping is what the post addresses, so the ping must store it in {external_id} before anything else. The state machine NEW → LOAN_OFFER_GENERATED → ACCEPTED → COMPLETED → LOAN_ISSUED Status Meaning Terminal NEW Submitted, offer not yet generated no, keep polling LOAN_OFFER_GENERATED Offer ready, accept or cancel it no, accept ACCEPTED The client accepted the offer yes, success COMPLETED Processing has started yes, success LOAN_ISSUED Loan paid out yes, success INVALID Failed validation yes, rejection CANCELLED Failed rule checks, or the client declined yes, rejection FAILED Processing ended in an error yes, rejection EXPIRED Did not finish in time yes, rejection Every one of these needs a branch, including the terminal ones you do not expect to see. A status missing from the loop conditions is a Dead End waiting to happen, and this API has nine of them. Cancel the offers you do not take POST /requests/{request_uuid}/cancel closes an offer that will not be accepted. If it is never called, ViaSMS keeps the application open. The next lead from the same person then comes back with error_code: OPEN_LOAN_APPLICATION, a rejection the integration caused itself. An integration that polls, gives up on the Breaker and walks away without cancelling manufactures its own duplicates. Calls POST {endpoint}/api/public/partners/{partner_id}/requests GET {endpoint}/api/public/partners/{partner_id}/requests/{external_id} POST {endpoint}/api/public/partners/{partner_id}/requests/{external_id}/accept POST {endpoint}/api/public/partners/{partner_id}/requests/{external_id}/cancel X-Api-Key: {token} Content-Type: application/json format: application/json Set format: application/json on every node that sends a JSON body. It is not inherited from another node, and a request without it is refused with 400. The GET calls take no body. Guard them: when {external_id} is empty the URL collapses to a trailing slash and the advertiser answers 404, which reads as a broken endpoint rather than as a missing identifier. The advertiser restricts access by IP address, so the addresses the calls originate from have to be registered with them before anything works. Request fields Field Required Value first_name yes {g_name_first} last_name yes {g_name_last} national_id yes {g_id_national_number} with the slash email yes {g_email} mobile_phone yes {g_phone} income_source yes {g_fin_type}, see enums net_monthly_income yes {g_fin_income} living_expenses yes {g_fin_expenses} expenses_on_existing_loans yes {g_fin_expenses_credit} requested_principal yes {g_amount} national_id goes in the Czech written form with the slash: {g_id_national_number} always regex_replace (\d{6})(\d{3,4}) → $1/$2 expenses_on_existing_loans is required. Send 0 rather than leaving it empty, an empty required field is refused. Enums income_source: EMPLOYMENT, SELF_EMPLOYMENT, SOCIAL_OR_PARENTAL_SUPPORT, PENSION, OTHER. Unemployed has no option; map it to OTHER. Outcomes errors and field_errors are present on every response and empty on success, which is what makes them usable as conditions. But only with an index. {parsedBody.errors.0.error_code} resolves; {parsedBody.errors.error_code} comes back as literal text, and literal text is never empty, so an “is not empty” test on it fires on every single response. A flow built that way labels every lead with the same rejection and never reaches its own success branch. Recognised by HTTP Meaning Reject reason Frequency status: NEW, no errors 200 Submitted, poll for the offer , common status: LOAN_OFFER_GENERATED 200 Offer ready, accept it , common status ~ `ACCEPTED COMPLETED LOAN_ISSUED` 200 Converted errors.0.error_code: OPEN_LOAN_APPLICATION 200 An application is already open Existing Customer common field_errors.0.field_name present 200 A field failed validation Product Mismatch occasional status: INVALID 200 Failed validation Not Eligible occasional status: CANCELLED 200 Failed rule checks or client declined Cancelled by Advertiser occasional status: FAILED 200 Processing error Unspecified rare status: EXPIRED 200 Not finished in time Expired rare Cloudflare error page 530 Advertiser unreachable , (technical) rare field_errors names the field, so {reason_detail} should carry both parts: {parsedBody.field_errors.0.field_name}: {parsedBody.field_errors.0.error_message}. OPEN_LOAN_APPLICATION is worth watching rather than accepting. Some of it is genuine repeat traffic; some of it is applications this integration opened and never cancelled. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, submitted, both error arrays checked, with the index: {status} equals 200 {parsedBody.errors.0.error_code} is empty {parsedBody.field_errors.0.field_name} is empty Ping, field validation failed: {parsedBody.field_errors.0.field_name} is not empty Ping, business error: {parsedBody.errors.0.error_code} is not empty Status poll, keep waiting: {parsedBody.status} equals NEW Status poll, accept the offer: {parsedBody.status} equals LOAN_OFFER_GENERATED Status poll, converted: {parsedBody.status} regex match ACCEPTED|COMPLETED|LOAN_ISSUED Status poll, refused: {parsedBody.status} regex match INVALID|CANCELLED|FAILED|EXPIRED The polling loop needs a Breaker with its count in the title. Watch the synchronous limit while setting it, the applicant is on a loading screen for the whole loop. Stored values Parameter Source {external_id} {parsedBody.request_uuid} from the ping {redirect_url} {parsedBody.redirect_url} from the status call Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to VistaCredit (CZ) Advertiser VistaCredit Country CZ Segment Finance Product Loan Integration type Lead generation Flows Ping → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -700, "y": 220 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "ping", "beType": "integration" } } }, { "id": "2-1", "type": "startNode", "position": { "x": -700, "y": -240 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -500, "y": 220 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "7000", "value2": "", "modification": "replace", "pattern": "", "output": "7000" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -280, "y": 220 }, "data": { "formData": { "active": true, "title": "Ping", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/api/leads/", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Token {token}" } ], "query": [], "body": [ { "key": "key", "value": "{eid}" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "income", "value": "{data_monthly_income}" }, { "key": "period", "value": "35" }, { "key": "expenses", "value": "{data_expenses}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "birth_number", "value": "{data_nin}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "endNode", "position": { "x": 59.055744069899, "y": 113.51669471981 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 28.040888484979, "y": 255.8140914298 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody.amount.0}", "operator": "regex_match", "value": "Částka úvěru", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.period.0}", "operator": "regex_match", "value": "Doba úvěru", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "živnostensk", "value2": "", "modification": "replace", "pattern": "", "output": "Not Eligible" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "rejstříku", "value2": "", "modification": "replace", "pattern": "", "output": "Poor Credit" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "pracovní dobu", "value2": "", "modification": "replace", "pattern": "", "output": "Outside Hours" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "Podezřelá", "value2": "", "modification": "replace", "pattern": "", "output": "Fraud" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "černé listině", "value2": "", "modification": "replace", "pattern": "", "output": "Blacklist" }, { "source": "{parsedBody.birth_number.0}", "operator": "regex_match", "value": "Věk", "value2": "", "modification": "replace", "pattern": "", "output": "Age" }, { "source": "{parsedBody.non_field_errors.0}", "operator": "regex_match", "value": "již existuje", "value2": "", "modification": "replace", "pattern": "", "output": "Existing Customer" }, { "source": "{parsedBody.birth_number.0}", "operator": "regex_match", "value": "už evidováno", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" }, { "source": "{parsedBody.key.0}", "operator": "regex_match", "value": "Duplicit", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 230.5131077459, "y": 277.92982013277 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "2-2", "type": "httpNode", "position": { "x": -460, "y": -240 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "PUT", "endpoint": "{endpoint}/api/leads/{eid}/", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Token {token}" } ], "query": [], "body": [ { "key": "email", "value": "{data_email}" }, { "key": "phone_number", "value": "{data_cell_phone}" } ], "signature": null, "insecure": null } } }, { "id": "2-3", "type": "setNode", "position": { "x": -186.89219012998, "y": -340.47212796505 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.login_url}" }, { "key": "{external_id}", "value": "{parsedBody.loans.0.id}" } ] } } }, { "id": "2-5", "type": "endNode", "position": { "x": 32.903367445122, "y": -321.37501781322 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "2-4", "type": "modifyFieldNode", "position": { "x": -180, "y": -180 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{status}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "http {status}: {body}" } ] } ] } } }, { "id": "2-6", "type": "endNode", "position": { "x": 49, "y": -168 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-1-2-2", "source": "2-1", "target": "2-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "400", "output2": "" } ] } }, { "id": "edge-1-5-1-6", "source": "1-5", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-2-2-3", "source": "2-2", "target": "2-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" } ] } }, { "id": "edge-2-2-2-4", "source": "2-2", "target": "2-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "400", "output2": "" } ] } }, { "id": "edge-2-3-2-5", "source": "2-3", "target": "2-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-2-4-2-6", "source": "2-4", "target": "2-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details The ping creates a lead record and returns the advertiser’s decision immediately approval or a stated reason. Nothing is billable at that point. The post attaches the contact details to the approved lead, which is what converts it into a customer and returns the URL the applicant is sent to. Between the two, the lead is identified by a key that you choose and send yourself. Almost all rejections happen at the ping. Expect the large majority of leads to be turned down there, most often for a missing trade licence. Rejections carry a readable Czech sentence, so the reject reason mapping is worth doing properly. What will be needed from advertiser Key Purpose endpoint Base API URL. token API token used in Authorization: Token …. Flows Ping, POST /api/leads/. Creates the lead and decides. 201 is approval, 400 is a rejection with a reason. Send key yourself; the same value identifies the lead later. Post, PUT /api/leads/{key}/. Adds phone and email. This is the step that converts the lead into a customer account and triggers the welcome email, so it must not run for a lead the ping did not approve. Returns login_url. The post needs nothing from the ping response, it addresses the lead by the same key the ping sent, so the two flows stay independent, as they should. The advertiser also exposes endpoints for checking a lead’s later state. That belongs to the Tracking API, not to the integration, and is configured separately. Calls Ping POST {endpoint}/api/leads/ Authorization: Token {token} Content-Type: application/json format: application/json Post PUT {endpoint}/api/leads/{send_id}/ Authorization: Token {token} Content-Type: application/json format: application/json A missing or invalid token returns 401 on every endpoint. Request fields Ping Field Type Required Value key string yes {send_id} first_name string yes {g_name_first} last_name string yes {g_name_last} birth_number string yes {g_id_national_number} amount number yes {g_amount}, capped period number yes {g_period} income number no {g_fin_income} expenses number no {g_fin_expenses} loan_payments number no {g_fin_expenses_credit} mailing_address.street string no {g_address_contact_street} mailing_address.house_number string no {g_address_contact_street_number} mailing_address.city string no {g_address_contact_city} mailing_address.postal_code string no {g_address_contact_zip} key is what ties the two flows together, so it has to be a value you can reproduce in the post. {send_id} is the natural choice. Sending a key that already exists returns a duplicate rejection. amount is capped at 7000, and anything above is rejected outright. period accepts up to 70 days. birth_number goes as plain digits, no slash. On capping the amount Where a request exceeds the advertiser’s maximum, send the maximum rather than the requested figure, but agree it with them first. Translating a higher request down is right only when they would otherwise reject the lead outright. Where they would have made a smaller offer on their own, send what the applicant actually asked for and let them answer. This is the one place the general rule bends: amount, term and product are the request itself, so they are normally passed through untouched. Post Field Type Required Value phone_number string yes {g_phone} email string yes {g_email} callback_url string no Tracking API endpoint, configured separately Enums None. The advertiser takes no coded values, no employment type, no housing status, no bank code. Everything is a name, a number or a date. Outcomes loans is empty at the ping and holds one entry after the post: the loan does not exist until the contact details arrive. login_url appears only on the post response. Recognised by HTTP Meaning Reject reason Frequency key present, loans: [] 201 Approved, proceed to post , common login_url present 200 Converted , common non_field_errors ~ živnostensk 400 No valid or active trade licence Not Eligible common birth_number ~ Věk žadatele 400 Outside the accepted age range Age common non_field_errors ~ Uživatel již existuje 400 Already a customer Existing Customer occasional birth_number ~ Neplatné rodné číslo 400 Malformed national ID Invalid Data occasional birth_number ~ už evidováno 400 This person is already on file Duplicate occasional non_field_errors ~ černé listině 400 On the advertiser’s blocklist Blacklist rare non_field_errors ~ rejstříku 400 Found in a debtor register Poor Credit rare key ~ Duplicitní hodnota 400 The key was used before Duplicate documented only amount ~ Částka úvěru 400 Amount outside the product range Product Mismatch documented only period ~ Doba úvěru 400 Term outside the product range Product Mismatch documented only non_field_errors ~ pracovní dobu 400 Outside the advertiser’s hours Outside Hours documented only non_field_errors ~ Podezřelá 400 Suspicious business or contact address Fraud documented only any field ~ Toto pole je vyžadováno 400 Required field missing Invalid Data documented only Match a substring, not the whole sentence. The exact wording drifts: the documentation gives Uživatel je na černé listině while the live response appends a source, as in Uživatel je na černé listině (RealMoney). The trade-licence rejection arrives in two wordings, nemá platné and nemá aktivní, which mean the same thing. Matching černé listině and živnostensk covers both. The rejection body is a map of field name to a list of messages, so a single message is at {parsedBody.non_field_errors.0} or {parsedBody.birth_number.0}. Those elements are strings and can be matched directly. Set {reason_detail} from {body} on one unconditional row, it covers every shape at once. Rows marked documented only have not been seen in production. Map them anyway; they cost one row each and a Dead End costs a report line. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Ping, approved: {status} equals 201 {parsedBody.key} is not empty Ping, rejected, scoped to the advertiser’s own answer, not to the status code: {status} equals 400 Post, converted: {status} equals 200 {parsedBody.login_url} is not empty Nothing else needs a branch. A 404 returns the advertiser’s marketing page as HTML rather than a business answer, and 401 means the token is wrong, both are technical responses and PalDock reports them on its own. Stored values Parameter Source Step {external_id} {parsedBody.loans.0.id} Post {redirect_url} {parsedBody.login_url} Post There is nothing worth storing from the ping. The lead is addressed by the key you sent, and the loan does not exist until the post has run. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Volsor (CZ) Advertiser Volsor Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -700, "y": 0 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -470, "y": 0 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "20000", "value2": "", "modification": "replace", "pattern": "", "output": "20000" } ] }, { "fieldName": "{data_employed_time}", "fields": [ { "source": "{data_employed_time}", "operator": "equals", "value": "3-month", "value2": "", "modification": "replace", "pattern": "", "output": "3" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-year", "value2": "", "modification": "replace", "pattern": "", "output": "10" }, { "source": "{data_employed_time}", "operator": "equals", "value": "1-2-year", "value2": "", "modification": "replace", "pattern": "", "output": "24" }, { "source": "{data_employed_time}", "operator": "equals", "value": "2-5-year", "value2": "", "modification": "replace", "pattern": "", "output": "48" }, { "source": "{data_employed_time}", "operator": "equals", "value": "5-year-plus", "value2": "", "modification": "replace", "pattern": "", "output": "66" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "HOME_OWNER" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "rent", "value2": "", "modification": "replace", "pattern": "", "output": "TENANT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "CO_OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE_BENEFIT" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "MATERNITY_LEAVE" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "PENSION" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_company_number_imported}", "fields": [ { "source": "{data_company_number_imported}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" }, { "source": "{data_company_number_imported}", "operator": "regex_not_match", "value": "^\\d{8}$", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_city}", "fields": [ { "source": "{data_contact_city}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_house_number}", "fields": [ { "source": "{data_contact_house_number}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_street}", "fields": [ { "source": "{data_contact_street}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] }, { "fieldName": "{data_contact_zip}", "fields": [ { "source": "{data_contact_zip}", "operator": "is_empty", "value": "", "value2": "", "modification": "do_not_send", "pattern": "", "output": "" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -220, "y": 0 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/leads/", "timeout": 30, "format": "application/json", "parser": "json", "notsend": "null", "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" }, { "key": "Authorization", "value": "Token {token}" } ], "query": [], "body": [ { "key": "zip", "value": "{data_zip}" }, { "key": "city", "value": "{data_city}" }, { "key": "agree", "value": "1" }, { "key": "email", "value": "{data_email}" }, { "key": "period", "value": "{data_period}" }, { "key": "street", "value": "{data_street}" }, { "key": "country", "value": "CZ" }, { "key": "product", "value": "payday" }, { "key": "employer", "value": "{data_employer}" }, { "key": "expenses", "value": "{data_expenses}" }, { "key": "bank_code", "value": "{data_bank_code}" }, { "key": "job_title", "value": "{data_job_title}" }, { "key": "last_name", "value": "{data_last_name}" }, { "key": "cell_phone", "value": "{data_cell_phone}" }, { "key": "first_name", "value": "{data_first_name}" }, { "key": "ip_address", "value": "{ip_address}" }, { "key": "contact_zip", "value": "{data_contact_zip}" }, { "key": "home_status", "value": "{data_home_status}" }, { "key": "income_type", "value": "{data_income_type}" }, { "key": "birth_number", "value": "{data_nin}" }, { "key": "contact_city", "value": "{data_contact_city}" }, { "key": "house_number", "value": "{data_house_number}" }, { "key": "employed_time", "value": "{data_employed_time}" }, { "key": "account_number", "value": "{data_account_number}" }, { "key": "company_number", "value": "{data_company_number_imported}" }, { "key": "contact_street", "value": "{data_contact_street}" }, { "key": "employer_phone", "value": "{data_employer_phone}" }, { "key": "monthly_income", "value": "{data_monthly_income}" }, { "key": "employer_address", "value": "{data_employer_address}" }, { "key": "requested_amount", "value": "{data_requested_amount}" }, { "key": "remarketing_agree", "value": "0" }, { "key": "third_party_agree", "value": "0" }, { "key": "contact_house_number", "value": "{data_contact_house_number}" }, { "key": "identity_card_number", "value": "{data_identity_card_number}" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 40, "y": -110 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.redirect_url}" }, { "key": "{external_id}", "value": "{parsedBody.id}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 300, "y": -110 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 40, "y": 150 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{parsedBody.status}", "operator": "equals", "value": "FAIL", "value2": "", "modification": "replace", "pattern": "", "output": "Invalid Data" }, { "source": "{parsedBody.errors.period.0}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.errors.requested_amount.0}", "operator": "is_not_empty", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" }, { "source": "{parsedBody.errors.birth_number.0}", "operator": "contains", "value": "Neplatný věk", "value2": "", "modification": "replace", "pattern": "", "output": "Age" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 300, "y": 150 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "201", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "OK", "output2": "" }, { "value": "{parsedBody.redirect_url}", "operator": "is_not_empty", "output": "", "output2": "" }, { "value": "{parsedBody.id}", "operator": "is_not_empty", "output": "", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "400", "output2": "" }, { "value": "{parsedBody.status}", "operator": "equals", "output": "FAIL", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details A lead broker rather than a lender. One call, and an unusually clean answer: 201 with a redirect_url when accepted, 400 with a per-field error map when not. One field dominates this integration and it is not a credit decision. company_number is validated as a Czech IČO, and anything that is not exactly eight digits passing the checksum is refused. Sent unguarded, it accounts for more than half of all rejections. Drop it rather than repairing it. A value that is empty, or that does not match ^\d{8}$, goes out of the request with do-not-send. Sending a placeholder or a trimmed version turns a missing field into an invalid one, which is worse. Volsor also asks for exclusivity: a lead they accept is not to be sent anywhere else. What will be needed from advertiser Key Purpose endpoint Base API URL. token API token used in Authorization: Token …. Flows Post, POST /leads/. Creates the lead and decides. Calls POST {endpoint}/leads/ Authorization: Token {token} Content-Type: application/json format: application/json notsend: null Request fields Field Required Value first_name yes {g_name_first} last_name yes {g_name_last} birth_number yes {g_id_national_number} identity_card_number yes {g_id_card_number} email yes {g_email} cell_phone yes {g_phone} street yes {g_address_street} house_number yes {g_address_street_number} city yes {g_address_city} zip yes {g_address_zip} contact_street no {g_address_contact_street} contact_house_number no {g_address_contact_street_number} contact_city no {g_address_contact_city} contact_zip no {g_address_contact_zip} home_status yes {g_home_type}, see enums contact_home_status no {g_home_type}, see enums income_type yes {g_fin_type}, see enums monthly_income yes {g_fin_income} expenses yes {g_fin_expenses} employer no {g_employer_name} employer_address no {g_employer_address} employer_phone no {g_employer_phone} job_title no {g_employ_position} employed_time no {g_employ_time}, see enums company_number self-employed {g_company_registration}, exactly eight digits account_number yes {g_bank_account_number} bank_code yes {g_bank_account_code}, see enums requested_amount yes {g_amount}, 500 to 20 000 period yes {g_period}, 1 to 30 days product yes payday country yes CZ ip_address yes {ip_address} agree yes 1 remarketing_agree no {g_consent_marketing} third_party_agree no 0 company_number must be exactly eight digits and pass the Czech IČO checksum. Two do-not-send rows cover it: one on is_empty, one on regex_not_match ^\d{8}$. Without them this is the single largest source of rejections in the whole integration. bank_code and home_status are closed sets. A value outside them is refused with the value quoted back, so an unmapped bucket shows up plainly in the reject detail. On capping the amount Where a request exceeds 20 000, send 20 000 rather than the requested figure, but agree it with them first. Translating a higher request down is right only when they would otherwise reject the lead outright. Where they would have made a smaller offer on their own, send what the applicant actually asked for and let them answer. Enums income_type: EMPLOYED, PART_TIME_EMPLOYMENT, SELF_EMPLOYED, PENSION, MATERNITY_LEAVE, BENEFITS, SAVINGS, STUDENT, UNEMPLOYED, OTHER. home_status: HOME_OWNER, TENANT, DORMITORY, HOSTEL, MINISTRY, EMPLOYEE_BENEFIT, CO_OWNED. Note that rent is not a value; it is TENANT. employed_time is a number of months: 0, 3 for one to three, 5 for four to seven, 10 for seven to twelve, 24, 36, 48, 60, and 66 for more than five years. Where the form’s bucket falls between two of these, choose the one that presents the lead as qualifying. bank_code is the Czech bank code, but only from Volsor’s own list. Codes such as 0005 and 0231 are refused. Outcomes The rejection body is {"status": "FAIL", "errors": {...}}, where errors is keyed by field name and each value is a list of messages. One response can name several fields at once, so the reject reason should be read from the field that matters most rather than from the first key. Recognised by HTTP Meaning Reject reason Frequency status: OK + redirect_url + id 201 Accepted common errors.company_number[] ~ Neplatná hodnota 400 Invalid or missing IČO Invalid Data common when unguarded errors.account_number[] ~ Nesprávné Číslo účtu 400 Invalid account number Invalid Data occasional errors.house_number[] ~ neodpovídá požadovanému formátu 400 Malformed house number Invalid Data occasional errors.zip[] ~ neodpovídá požadovanému formátu 400 Malformed postcode Invalid Data rare errors.cell_phone[] ~ Nesprávný formát 400 Malformed phone Invalid Data rare errors.home_status[] ~ není platnou možností 400 Housing value outside the set Invalid Data rare errors.bank_code[] ~ není platnou možností 400 Bank code outside the set Invalid Data rare errors.birth_number[] ~ Neplatný věk 400 Outside the age range Age rare errors.period[] present 400 Term outside 1 to 30 days Product Mismatch documented only errors.requested_amount[] present 400 Amount outside 500 to 20 000 Product Mismatch documented only HTML error page 500 Advertiser-side failure rare Almost every rejection here is a payload problem rather than a credit decision. That is worth naming: a run of Invalid Data on one field means either the field should be dropped when it cannot be valid, or the form should validate it. Neither is a repair regex in this blueprint. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Accepted: {status} equals 201 {parsedBody.status} equals OK {parsedBody.id} is not empty {parsedBody.redirect_url} is not empty Refused: {status} equals 400 {parsedBody.status} equals FAIL 500 returns an HTML page and gets no branch. Stored values Parameter Source {external_id} {parsedBody.id} {redirect_url} {parsedBody.redirect_url} Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you. #### Sell leads to Zaplo (CZ) Advertiser Zaplo Country CZ Segment Finance Product Loan Integration type Lead generation Flows → Post Get Started Copy blueprint Use global fields and skip mapping entirely Every prebuilt integration is already mapped to PalDock’s global fields. Populate them once in your lead structure, whether leads arrive through the API or form, and the same fields feed every integration you run. Integration overview This prebuilt PalDock integration connects your lead flow directly to the advertiser. It handles field mapping, request delivery and response processing, so you can start sending leads without building the integration from scratch. The integration uses PalDock’s global fields and returns standardized outcomes for reporting and routing, while preserving advertiser response details for troubleshooting. Blueprint Blueprint for new customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -420, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "16000", "value2": "", "modification": "replace", "pattern": "", "output": "16000" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "RETIREE" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "RENT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "WITH_RELATIVES" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYER" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -180, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/affiliate-api", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "city", "value": "{data_city}" }, { "key": "term", "value": "{data_period}" }, { "key": "email", "value": "{data_email}" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "cardId", "value": "{data_identity_card_number}" }, { "key": "street", "value": "{data_street}" }, { "key": "lastName", "value": "{data_last_name}" }, { "key": "termType", "value": "DAYS" }, { "key": "firstName", "value": "{data_first_name}" }, { "key": "acceptNews", "value": "false" }, { "key": "personalId", "value": "{data_nin}" }, { "key": "postalCode", "value": "{data_zip}" }, { "key": "mobilePhone", "value": "{data_cell_phone}" }, { "key": "clientIncome", "value": "{data_monthly_income}" }, { "key": "newsAccepted", "value": "false" }, { "key": "affiliateToken", "value": "{eid}" }, { "key": "clientExpenses", "value": "{data_expenses}" }, { "key": "employmentType", "value": "{data_income_type}" }, { "key": "acceptAgreement", "value": "true" }, { "key": "applicationType", "value": "WEB" }, { "key": "houseFlatNumber", "value": "{data_house_number}" }, { "key": "acceptDataSharing", "value": "true" }, { "key": "accommodationType", "value": "{data_home_status}" }, { "key": "affiliateProvider", "value": "{partner_id}" }, { "key": "bankAccountNumber", "value": "{data_account_number}/{data_bank_code}" }, { "key": "numberOfHouseholdMembers", "value": "1" }, { "key": "numberOfEmployedHouseholdMembers", "value": "1" } ], "signature": null, "insecure": null } } }, { "id": "1-7", "type": "setNode", "position": { "x": 100, "y": -80 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.url}" }, { "key": "{external_id}", "value": "{custom_api_token}" } ] } } }, { "id": "1-8", "type": "endNode", "position": { "x": 340, "y": -80 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-4", "type": "modifyFieldNode", "position": { "x": 100, "y": 160 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody}", "operator": "regex_match", "value": "/login", "value2": "", "modification": "replace", "pattern": "", "output": "Duplicate" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 340, "y": 160 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 180, "y": -160 }, "data": { "formData": { "active": true, "title": "Extract ID", "subtitle": "", "data": [ { "fieldName": "{custom_api_token}", "fields": [ { "source": "{parsedBody.url}", "operator": "always", "value": "", "value2": "", "modification": "first_regex_match", "pattern": "", "output": "(?<=apiToken=)[^&]+" } ] } ] } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "/continue/affiliate", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "/continue/affiliate", "output2": "" } ] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-7-1-8", "source": "1-7", "target": "1-8", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } Blueprint for repeated customers { "nodes": [ { "id": "1-1", "type": "startNode", "position": { "x": -620, "y": 40 }, "data": { "formData": { "active": true, "title": "", "subtitle": "", "flow": "post", "beType": "integration" } } }, { "id": "1-2", "type": "modifyFieldNode", "position": { "x": -420, "y": 40 }, "data": { "formData": { "active": true, "title": "Transform data", "subtitle": "", "data": [ { "fieldName": "{data_requested_amount}", "fields": [ { "source": "{data_requested_amount}", "operator": "is_greater_than", "value": "35000", "value2": "", "modification": "replace", "pattern": "", "output": "35000" } ] }, { "fieldName": "{data_income_type}", "fields": [ { "source": "{data_income_type}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "full-time", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYEE" }, { "source": "{data_income_type}", "operator": "equals", "value": "self-employed", "value2": "", "modification": "replace", "pattern": "", "output": "SELF_EMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "parental", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" }, { "source": "{data_income_type}", "operator": "equals", "value": "pension", "value2": "", "modification": "replace", "pattern": "", "output": "RETIREE" }, { "source": "{data_income_type}", "operator": "equals", "value": "unemployed", "value2": "", "modification": "replace", "pattern": "", "output": "UNEMPLOYED" }, { "source": "{data_income_type}", "operator": "equals", "value": "other", "value2": "", "modification": "replace", "pattern": "", "output": "OTHER" } ] }, { "fieldName": "{data_home_status}", "fields": [ { "source": "{data_home_status}", "operator": "equals", "value": "owner", "value2": "", "modification": "replace", "pattern": "", "output": "OWNED" }, { "source": "{data_home_status}", "operator": "equals", "value": "tenant", "value2": "", "modification": "replace", "pattern": "", "output": "RENT" }, { "source": "{data_home_status}", "operator": "equals", "value": "family", "value2": "", "modification": "replace", "pattern": "", "output": "WITH_RELATIVES" }, { "source": "{data_home_status}", "operator": "equals", "value": "employ-benefits", "value2": "", "modification": "replace", "pattern": "", "output": "EMPLOYER" } ] } ] } } }, { "id": "1-3", "type": "httpNode", "position": { "x": -180, "y": 40 }, "data": { "formData": { "active": true, "title": "Post", "subtitle": "", "method": "POST", "endpoint": "{endpoint}/affiliate-api", "timeout": 30, "format": "application/json", "parser": "json", "notsend": null, "convert_data": null, "headers": [ { "key": "Content-Type", "value": "application/json" } ], "query": [], "body": [ { "key": "city", "value": "{data_city}" }, { "key": "term", "value": "{data_period}" }, { "key": "email", "value": "{data_email}" }, { "key": "amount", "value": "{data_requested_amount}" }, { "key": "cardId", "value": "{data_identity_card_number}" }, { "key": "street", "value": "{data_street}" }, { "key": "lastName", "value": "{data_last_name}" }, { "key": "termType", "value": "DAYS" }, { "key": "firstName", "value": "{data_first_name}" }, { "key": "acceptNews", "value": "false" }, { "key": "personalId", "value": "{data_nin}" }, { "key": "postalCode", "value": "{data_zip}" }, { "key": "mobilePhone", "value": "{data_cell_phone}" }, { "key": "clientIncome", "value": "{data_monthly_income}" }, { "key": "newsAccepted", "value": "false" }, { "key": "affiliateToken", "value": "{eid}" }, { "key": "clientExpenses", "value": "{data_expenses}" }, { "key": "employmentType", "value": "{data_income_type}" }, { "key": "acceptAgreement", "value": "true" }, { "key": "applicationType", "value": "WEB" }, { "key": "houseFlatNumber", "value": "{data_house_number}" }, { "key": "acceptDataSharing", "value": "true" }, { "key": "accommodationType", "value": "{data_home_status}" }, { "key": "affiliateProvider", "value": "{partner_id}" }, { "key": "bankAccountNumber", "value": "{data_account_number}/{data_bank_code}" }, { "key": "numberOfHouseholdMembers", "value": "1" }, { "key": "numberOfEmployedHouseholdMembers", "value": "1" } ], "signature": null, "insecure": null } } }, { "id": "1-4", "type": "setNode", "position": { "x": 100, "y": -80 }, "data": { "formData": { "active": true, "title": "Store response", "subtitle": "", "fields": [ { "key": "{redirect_url}", "value": "{parsedBody.url}" } ] } } }, { "id": "1-6", "type": "endNode", "position": { "x": 340, "y": -80 }, "data": { "formData": { "active": true, "title": "Success", "subtitle": "", "success": "success" } } }, { "id": "1-5", "type": "modifyFieldNode", "position": { "x": 100, "y": 160 }, "data": { "formData": { "active": true, "title": "Reject reason", "subtitle": "", "data": [ { "fieldName": "{reason}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "Unspecified" }, { "source": "{parsedBody}", "operator": "regex_match", "value": "/continue/affiliate", "value2": "", "modification": "replace", "pattern": "", "output": "Product Mismatch" } ] }, { "fieldName": "{reason_detail}", "fields": [ { "source": "{body}", "operator": "always", "value": "", "value2": "", "modification": "replace", "pattern": "", "output": "{body}" } ] } ] } } }, { "id": "1-7", "type": "endNode", "position": { "x": 340, "y": 160 }, "data": { "formData": { "active": true, "title": "Rejected", "subtitle": "", "success": "failed" } } } ], "edges": [ { "id": "edge-1-1-1-2", "source": "1-1", "target": "1-2", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-2-1-3", "source": "1-2", "target": "1-3", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-3-1-4", "source": "1-3", "target": "1-4", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_match", "output": "/login", "output2": "" } ] } }, { "id": "edge-1-3-1-5", "source": "1-3", "target": "1-5", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [ { "value": "{status}", "operator": "equals", "output": "200", "output2": "" }, { "value": "{parsedBody}", "operator": "regex_not_match", "output": "/login", "output2": "" } ] } }, { "id": "edge-1-4-1-6", "source": "1-4", "target": "1-6", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } }, { "id": "edge-1-5-1-7", "source": "1-5", "target": "1-7", "type": "customEdge", "data": { "active": true, "title": "", "subtitle": "", "conditions": [] } } ] } How it works Copy the blueprint and paste it in your PalDock workspace– Create a new integration in your workspace and paste the blueprint. Every field arrives prefilled. Enter your credentials – Paste the secrets you received from advertiser and set your Pingtree Send a test lead – Verify the response, then switch the channel live. FAQ Do I need my own contract with this advertiser? Yes. PalDock delivers leads on your behalf, so the commercial agreement and API credentials come from the advertiser directly. What happens to rejected leads? The advertiser returns its decision in the delivery response. PalDock reads it and moves rejected leads to the next buyer in your pingtree automatically, so a rejection does not need to end the lead’s journey. Can I change the field mapping? Yes, but we do not recommend it. Blueprints are already mapped to PalDock’s global fields. If you use local fields, you need to remap each integration separately. How long does setup take? Few clicks, if you already have credentials. The blueprint arrives prefilled and mapped to PalDock’s global fields, so if your lead structure uses them, there is nothing to map. If you use local fields, you map them once. What the integration does Start sending leads in 3 clicks Copy the prebuilt blueprint, add your credentials and start sending leads. No coding, no integration work. Real-time lead delivery Send leads to the advertiser instantly as they arrive, without exports, batches or manual processing. No field mapping headache PalDock global fields work across all prebuilt integrations. Map your lead data once and reuse it everywhere. Know exactly why leads fail Get standardized rejection reasons for reporting and advertiser’s response for the full context and troubleshooting. Get Started Copy blueprint API & integration details One call, one answer. There is no ping and no lookup, the affiliate endpoint registers the applicant and decides in the same request. The response is two fields wide, and everything hangs on them: { "resolution": "SUCCESS", "url": "https://registration.zaplo.cz/…" } { "resolution": "REJECTED" } What will be needed from advertiser Key Purpose endpoint Base API URL. partner_id Affiliate provider identifier. Flows Post, POST /affiliate-api. Registers and decides. Calls POST {endpoint}/affiliate-api Content-Type: application/json format: application/json Credentials travel in the body rather than a header: affiliateProvider is the partner identifier and affiliateToken carries the lead reference. Request fields Field Required Value firstName yes {g_name_first} lastName yes {g_name_last} personalId yes {g_id_national_number} cardId yes {g_id_card_number} email yes {g_email} mobilePhone yes {g_phone} street yes {g_address_street} houseFlatNumber yes {g_address_street_number} city yes {g_address_city} postalCode yes {g_address_zip} bankAccountNumber yes {g_bank_account_number}/{g_bank_account_code} clientIncome yes {g_fin_income} clientExpenses yes {g_fin_expenses} employmentType yes {g_fin_type}, see enums amount yes {g_amount} term yes {g_period} termType yes DAYS accommodationType yes {g_home_type}, see enums numberOfHouseholdMembers yes {g_household_members} numberOfEmployedHouseholdMembers yes {g_household_members_adults} applicationType yes WEB acceptAgreement yes true acceptDataSharing yes true acceptNews yes false unless the applicant opted in newsAccepted yes same value as acceptNews affiliateProvider yes {partner_id} affiliateToken yes {send_id} bankAccountNumber is the full account with the code appended after a slash, compose it in the HTTP node, not in a Modify step. acceptNews and newsAccepted are two names for the same consent and both are read. Send the same value into both. Enums employmentType: EMPLOYEE, SELF_EMPLOYED, RETIREE, UNEMPLOYED, OTHER. Maternity has no option, map it to OTHER. accommodationType: OWNED, RENT, WITH_RELATIVES, EMPLOYER. Which URL you get matters An accepted lead comes back with resolution: SUCCESS and a url, and the path of that URL says what kind of customer this is: URL path Meaning /continue/affiliate?apiToken=... New applicant, the registration continues on Zaplo /login Existing customer, they are sent to sign in Zaplo is therefore configured as two integrations, one selling new applicants and one selling returning ones, and each treats the other’s URL as Product Mismatch rather than as a sale. The apiToken in the new-applicant URL is the only durable reference the response gives. Extract it from {parsedBody.url} with first_regex_match and the pattern (?<=apiToken=)[^&]+. Outcomes Recognised by HTTP Meaning Reject reason Frequency resolution: SUCCESS, url ~ /continue/affiliate 200 Accepted, new applicant , occasional resolution: SUCCESS, url ~ /login 200 Accepted, existing customer , occasional resolution: REJECTED 200 Refused, no reason given Unspecified common errors[].message ~ Application is rejected 200 Refused by scoring Unspecified documented only errors[] on empty or malformed input 200 Payload refused Invalid Data documented only errors[] ~ credit limit exceeded 200 Over the limit Too Much Debt documented only REJECTED is almost all of the traffic and carries nothing else, no code, no message. Unspecified, and the volume is exactly the argument to take to the advertiser when asking for reason codes. The documented errors array does not appear in production; the live endpoint collapses everything into the one word. Map it anyway. Reject reasons come from the standard list. See Reject reason for what each one means and when to use it. Branching Match on resolution, not on the URL text. {parsedBody} is a parsed object, and a contains or regex condition against it matches nothing, the branch never fires. New-applicant integration, accepted: {status} equals 200 {parsedBody.resolution} equals SUCCESS {parsedBody.url} regex match /continue/affiliate Returning-customer integration, accepted: {status} equals 200 {parsedBody.resolution} equals SUCCESS {parsedBody.url} regex match /login Refused, a catch-all scoped to the business response: {status} equals 200 {parsedBody.resolution} regex not match ^SUCCESS$ Wrong kind of customer, on either integration: {status} equals 200 {parsedBody.resolution} equals SUCCESS {parsedBody.url} regex not match /continue/affiliate ← or /login 502 and 500 return an empty body and no business result. They get no branch. Stored values Parameter Source {external_id} apiToken extracted from {parsedBody.url} {redirect_url} {parsedBody.url} On the returning-customer flow the /login URL has no token, so there is nothing durable to store beyond the redirect. Get Started Copy blueprint Advertiser APIs change without warning When they do, leads stop being delivered, often before anyone notices. PalDock gives you delivery logs and alerts so you can catch it early. With Managed Integrations, we watch the connection and fix it for you.