We hold an Instagram access token for every connected account. Anyone who obtains one can speak as that creator. That single fact shapes most of what is on this page.
Instagram tokens
- Encrypted at rest with AES-256-GCM, with the key version stored alongside the ciphertext so keys can be rotated without a migration that reads every row.
- The plaintext exists in memory for the length of one API call and is written nowhere else. It appears in no log line, no response body and no error message — that is asserted by tests, not by a convention.
- Refreshed ahead of expiry by a scheduled job. If a refresh fails, the
connection enters an
expiringstate seven days out and you get an email and a banner, rather than silence and an automation that stopped. - Revoked with Meta when you disconnect, and when you delete your account.
Sessions
We use opaque server-side sessions, not JWTs, because revocation has to take effect immediately rather than whenever a token happens to expire.
- A long random value from a cryptographic source, stored only as a hash. A database leak yields no usable session.
- Delivered in a cookie that is
httpOnly,secureandSameSite=Lax. Never in local storage, never in a response body. - Sliding expiry: 14 days idle, 30 days absolute.
- Cross-site request forgery is handled by the cookie policy plus an origin check on every mutation.
- You can see every active session — device, browser, location, last seen — and end any of them, including all the others at once.
Passwords are hashed with a modern memory-hard algorithm. We never see or store the password itself, it cannot be recovered from the hash, and support cannot read it back to you. We do not enforce rotation, which produces worse passwords rather than better ones.
We do not publish the specific algorithm, its parameters or our library versions here. Naming them changes nothing for an honest reader and saves an attacker a step, and a page like this is read by both.
Access inside the company
- Data is scoped to a workspace at the query level, so one customer's request cannot return another customer's row.
- Staff access to production is by named account. There are no shared logins.
- Administrative privileges are not standing. They are elevated for a defined period with a reason recorded, and they drop automatically. A laptop stolen in March cannot read an account in June.
- Every administrative action is written to an append-only audit table by the same guard that authorises it, so an endpoint cannot forget to log itself.
Support access to your account
Sometimes answering a support question means seeing what you see. When that happens:
- It is read-only. Nobody can act as you.
- It lasts fifteen minutes, then it stops mid-session without warning. A longer investigation means starting another one and saying why again.
- It requires a written reason, recorded before it begins.
- Both ends are logged — the start with the reason, the end with whether a human ended it or it expired.
- It is never silent. It appears on your own security page like any other session, named, and you can end it yourself.
- It can never be used against another staff account, which would be a privilege-escalation path with no support value.
A support tool the customer cannot audit is a back door with a nicer name.
Payments
No card number, CVV, UPI PIN or bank credential ever reaches our servers. Razorpay and Stripe both run their own hosted checkout, and we receive a payment id and an amount. Credits are granted by a signature-verified webhook, never by a browser redirect, so a forged or replayed redirect grants nothing.
The application itself
- All traffic is served over TLS. There is no plaintext port.
- Comments, messages and uploaded documents are treated as untrusted input. Text coming from Instagram is never assembled into a model prompt as instruction; it is delimited and labelled as data, and a classifier trained on Hinglish and code-mixed prompt injection runs before anything is generated.
- A generated reply that is not supported by the creator's own retrieved content is not sent. It falls back to the creator's template.
- Every outbound action passes one policy gate. There is no bypass — the dispatch function will not compile without a decision object that only the gate can construct.
- There is a kill switch at three levels: global, workspace, connection. It is the first check the gate runs.
- Dependency versions are pinned, and upgrades are deliberate rather than automatic.
Logging and retention
Logs are structured and redacted at the point of writing: tokens, password hashes, session identifiers and message bodies are not in them. Raw webhook deliveries and policy decisions are kept 30 days; the model service's own log is kept 30 days. The full schedule is in the privacy notice.
If there is a breach
We keep a breach register with a 72-hour clock that starts when a suspicion is recorded, not when it is confirmed. We notify the Data Protection Board of India within 72 hours and affected people without delay, with what happened, what was exposed, and what to do.
The query that answers "who was affected" was written and tested before it was needed. Writing it under a 72-hour clock during an incident is how the number comes out wrong.
Reporting a vulnerability
Email security@postengage.ai. Include what you found and how to reproduce it. We acknowledge within two working days and tell you what we are doing.
We will not pursue you for a good-faith report, provided you do not access, modify or retain another person's data, do not degrade the service, and give us a reasonable window before publishing. We do not currently run a paid bug bounty, and we will not pretend otherwise.
What we do not claim
We have not completed a SOC 2 or an ISO 27001 audit, and we hold no security certification. If one is a requirement for you, ask before you buy rather than after.
Everything on this page is a description of how the system is built, and every item on it is something you can ask us to demonstrate.