Decide what you are rewarding
Both platforms expose several kinds of activity, and a program does not have to treat them alike. Finishing a single lesson and completing a full learning path represent different amounts of effort, and your Available Actions can reflect that.- Secure Code Warrior
- Security Journey
Does your source support an incremental read?
This is the question that determines how your integration is built, and the answer depends on which endpoint you chose above. An incremental read means the API can return only what changed since you last asked. Where it exists, you pull a handful of records each run. Where it does not, you pull everything every time and sort it out yourself.Yes — incremental
Pull only what changed, using the platform’s date parameter. Volume stays small and the ledger described below is a safety net rather than the mechanism.Security Journey
/path-enrollments supports updated_after.Secure Code Warrior assessments and leaderboard support startdate and enddate.No — full dump
Every call returns the complete history. You filter locally before doing anything expensive, and a ledger of what you have already credited becomes the integration rather than a convenience.Secure Code Warrior
/learning/progress returns all completions for all developers on every call.Security Journey /lesson-attempts documents no filtering.Check the current API reference for your platform before building. Date filtering tends to appear endpoint by endpoint rather than across an API, and parameters get added over time.
Connecting
- Secure Code Warrior
- Security Journey
Base URL: Keys come in Report, Admin, and Team varieties, and each endpoint specifies which ones authorise it. A Report key is enough for everything in this guide.Pagination: responses carry a
https://portal-api.securecodewarrior.com/api/v2European tenants use https://portal-api.eu.securecodewarrior.com/api/v2 instead. If you are not sure which applies, your Customer Success Manager can tell you.Authentication: an X-API-Key header carrying the token on its own, with no prefix.links object with total_pages and total_results. Compare total_results against what you actually received rather than assuming one call returned everything — /learning/progress serves 2000 records per page, so an organisation larger than that gets silently truncated.Configure the action in Katilyst
1
Create an Available Action
Create an Instance action named for what it recognises — Secure Code Warrior — Module Completed, for example. Set the Attribute it changes, the amount, and any conditions.Create a separate action for each kind of activity you decided to reward. One for lessons and one for completed paths, if that is your model.
2
Find your project ID
3
Find your action ID
id for each action you created. You will need one per activity type.The pattern
Five stages, whatever you build this in.Pull
Call the platform on a schedule. Daily is almost always enough — training completions arrive at human pace, and a tighter loop costs more for no benefit.If your endpoint supports an incremental read, pass a window slightly wider than your schedule interval. Two days against a daily run means a skipped or delayed run still catches its records.If it does not, you receive everything and move to the next stage.
Filter
Drop anything outside your window before doing anything else.This stage has to come first among the per-record steps. On a full-dump source it is the difference between examining a handful of records and examining thousands on every run. Filtering after a database lookup or an API call means paying for work you then discard.Use the completion timestamp the platform returns, and use the same wider-than-the-interval window as above. Overlap is safe because the next stage catches repeats.
Check the ledger
For each surviving record, ask whether you have credited this person for this item before.The ledger is a simple key-value store: a Make data store, a Zapier table, a database table, a file. The key identifies one person and one item — an email address and a course identifier, joined.Katilyst cannot do this for you. It records that an action was logged, not which course produced it, so two completions of different modules are indistinguishable to it. Without a ledger, every overlapping window credits the same work again.
Log the action
For records not already in the ledger, call Katilyst.Pass
dateTime from the platform’s completion timestamp rather than letting Katilyst stamp on receipt. For a nightly job the two differ by hours, and reporting by period depends on the real date.Put something recognisable in creator, and the course name in details — that is what appears in the champion’s own activity log.Record it
Write the key to the ledger, after the call succeeds.The ordering is deliberate. Writing first means a failed call permanently suppresses that credit with nobody noticing. Writing after means a successful call followed by a failed write credits again next run — visible in the champion’s log, and correctable.
Before the first live run: seed the ledger
On a full-dump source, skipping this step backfills everything. The first run sees every completion the platform has ever recorded, finds none of them in an empty ledger, and logs all of them. A developer who has been using the platform for two years collects two years of credit overnight, and the leaderboard stops meaning anything. Seed first:- Run the integration with the Katilyst call disabled and the ledger write enabled.
- Remove the date filter so everything passes through.
- Let it complete. The ledger now holds every existing completion, marked as already credited.
- Re-enable the call and restore the filter.
Worked example: Secure Code Warrior via Make.com
One implementation of the pattern. The stages map onto any workflow tool; the module names are Make’s.
Modules 6 and 9 share one key expression, which identifies a single person and a single course:
{{3.completed}} gives you that developer’s completions. Referencing the original response with empty brackets — {{2.data.developers[].completed}} — collects every completion by everyone, and each developer then gets credited for all of them.
Put the date filter at module 5, before the data store lookup. Filters cost nothing in Make; data store operations do. In the wrong position it saves nothing.
resource is an array, not a string. Secure Code Warrior returns a breadcrumb path. Use join() for both the ledger key and the details field.
Handle 409 rather than failing on it. A 409 means that person is not eligible for the action, which happens routinely when someone outside the champion program completes training. Without an error handler, a few of them halt the run and every later record in that batch is lost. Attach a handler to module 8 that resumes on 409 and let other statuses fail normally.
Set the scenario to process sequentially. Parallel execution lets two bundles both pass the ledger check before either writes.
Verify
- Two developers with multiple completions each. The only test that catches an incorrectly scoped iterator. Confirm each person is credited for their own work and nobody else’s.
- Run twice with no new activity. The second run should log nothing.
- Check your operation or task count on a quiet run. A number close to your developer count means the date filter is working. A number close to your total completion count means it is in the wrong place.
- Read an action back. Confirm
actionDatematches the completion time rather than when the job ran, and thatdetailsreads as a course name.
Troubleshooting
- Everyone is credited for everyone’s completions. The inner loop is reading the whole response rather than the current person’s records. This is invisible in a single-developer test.
- The same completions are credited on every run. Either the ledger is never written, or nothing acts on the lookup result. Both halves are needed: a filter that stops already-credited records, and a write that records new ones.
- The first run credited years of history. The ledger was not seeded. Credit can be removed in Katilyst, and seeding before the next run prevents a repeat.
- Consumption is far higher than expected. The date filter is positioned after an operation that costs something. Move it ahead of the ledger lookup.
- A
401from the training platform. Secure Code Warrior wantsX-API-Keywith a bare token; Security Journey wantsAuthorizationwith aBearerprefix. They are not interchangeable. - A
401from Katilyst. The key is invalid, missing, or sent without theAPI-Keyprefix on the header value. - A
409from Katilyst. That person is not eligible for the Available Action. The request was well formed and the program’s own rules declined it. - Some developers are never credited. Check the platform’s pagination. Compare the total it reports against the number of records you received — a large organisation can exceed one page.
Related
Core concepts
Instance versus State actions, guardrails, and how rewards are decided.
Log an action
Full reference for the endpoint this integration calls.
