Connect an ad account
Connects a Meta ad account with a system user access token.
The token must grant ads_read and reach the account; the account's name, currency and time zone come from Meta. The token is stored encrypted and never returned, and the first sync starts right away. Connecting an account that is connected already replaces its token and resumes a stopped sync; it answers 201 with the same account. Needs project:ads:manage.
Guide: Connect Meta Ads
A project secret key: vh_sk_... for production, vh_sk_test_... for test. Keep it on your servers.
In: header
Path parameters
The project's id, proj_.... A secret key works only in the project it belongs to.
Request body
application/json
TypeScript definitions
Use the request body type in TypeScript.
The ad platform: meta (Facebook and Instagram ads), the only one today.
The ad account id from Ads Manager, with or without the act_ prefix.
A system user access token with the ads_read permission on the account. Stored encrypted and never returned.
1 <= length <= 4096Days of history the first sync pulls, from 1 to 1095; defaults to 90. Asking a connected account for more pulls the earlier days too.
Examples
curl -X POST "https://api.voidhash.com/api/v1/projects/proj_tz4a98xxat96iws9zmbrgj3a/ads/accounts" \ -H "Authorization: Bearer vh_sk_..." \ -H "Content-Type: application/json" \ -d '{ "platform": "meta", "externalId": "act_1234567890", "accessToken": "EAAB...", "backfillDays": 90 }'{ "id": "ad_acct_k3m9x2c7v1b8n4q6w0e5r2t7", "projectId": "proj_tz4a98xxat96iws9zmbrgj3a", "platform": "meta", "externalId": "1234567890", "name": "Acme Fitness", "currency": "USD", "timezone": "Europe/Prague", "backfillDays": 90, "syncStatus": "pending", "lastSyncStartedAt": null, "lastSyncSucceededAt": null, "lastSyncErrorAt": null, "lastSyncError": null, "nextSyncAt": "2026-03-01T09:00:00.000Z", "spendCap": null, "createdAt": "2026-03-01T09:00:00.000Z"}{ "error": { "type": "invalid_request", "code": "ad_account_rejected", "message": "The access token does not grant ads_read. Generate the system user token with the ads_read permission." }}{ "error": { "type": "unauthenticated", "code": "invalid_api_key", "message": "This secret key is not valid." }}{ "error": { "type": "permission_denied", "code": "permission_denied", "message": "Insufficient permissions." }}{ "error": { "type": "not_found", "code": "project_not_found", "message": "There is no project proj_tz4a98xxat96iws9zmbrgj3a, or this credential cannot use it.", "param": "projectId" }}{ "error": { "type": "internal", "code": "internal_error", "message": "Something went wrong on our side. Try again, and contact support with the Request-Id header if it keeps failing." }}Response body
application/json
application/json
application/json
application/json
application/json
application/json
Errors
| Status | type | code | When |
|---|---|---|---|
| 400 | invalid_request | ad_account_rejected | When Meta rejects the token or the account, and message says what to change. |
It can also fail with the errors every operation shares, such as unauthenticated; see Errors.
More in Ad accounts
Something wrong or missing on this page? Tell us by email or on Discord.