Activity Validator
Use this tool to validate your ActivityStreams activities and objects against the specification.
Online Validators
ActivityPub.rocks Validator
The most comprehensive online validator:
URL: https://activitypub.rocks/tools/
Features:
- Validates ActivityStreams JSON
- Checks required properties
- Verifies JSON-LD context
- Tests HTTP Signatures
Go-Fed Validator
Testing tool from the go-fed project:
URL: https://go-fed.org/
Features:
- Comprehensive spec compliance
- Detailed error messages
Local Validation
Basic JSON Schema Validation
const Ajv = require('ajv');
const ajv = new Ajv();
const activitySchema = {
type: 'object',
required: ['@context', 'type', 'actor'],
properties: {
'@context': {
oneOf: [
{ type: 'string' },
{ type: 'array' }
]
},
type: { type: 'string' },
id: { type: 'string', format: 'uri' },
actor: {
oneOf: [
{ type: 'string', format: 'uri' },
{ type: 'object' }
]
},
object: {},
to: { type: 'array', items: { type: 'string' } },
cc: { type: 'array', items: { type: 'string' } }
}
};
function validateActivity(activity) {
const validate = ajv.compile(activitySchema);
const valid = validate(activity);
if (!valid) {
console.log('Validation errors:', validate.errors);
}
return valid;
}
Type-Specific Validation
function validateByType(activity) {
const errors = [];
// Common checks
if (!activity['@context']) {
errors.push('Missing @context');
}
if (!activity.type) {
errors.push('Missing type');
}
if (!activity.actor) {
errors.push('Missing actor');
}
// Type-specific checks
switch (activity.type) {
case 'Create':
if (!activity.object) {
errors.push('Create requires object');
}
if (activity.object && activity.object.attributedTo !== activity.actor) {
errors.push('Create object.attributedTo should match actor');
}
break;
case 'Follow':
if (!activity.object) {
errors.push('Follow requires object (target actor)');
}
break;
case 'Like':
case 'Announce':
if (!activity.object) {
errors.push(`${activity.type} requires object`);
}
break;
case 'Delete':
if (!activity.object) {
errors.push('Delete requires object');
}
break;
case 'Undo':
if (!activity.object) {
errors.push('Undo requires object (activity to undo)');
}
break;
}
return {
valid: errors.length === 0,
errors
};
}
Common Validation Errors
Missing @context
// ❌ Wrong
{
"type": "Note",
"content": "Hello"
}
// ✅ Correct
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Note",
"content": "Hello"
}
Invalid Actor URL
// ❌ Wrong - not a URL
{
"actor": "alice"
}
// ✅ Correct
{
"actor": "https://example.com/users/alice"
}
Missing Required Properties
// ❌ Wrong - Create without object
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"actor": "https://example.com/users/alice"
}
// ✅ Correct
{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"actor": "https://example.com/users/alice",
"object": {
"type": "Note",
"content": "Hello!"
}
}
Attribution Mismatch
// ❌ Wrong - actor doesn't match attributedTo
{
"type": "Create",
"actor": "https://example.com/users/alice",
"object": {
"type": "Note",
"attributedTo": "https://example.com/users/bob",
"content": "Hello"
}
}
Validation Checklist
For All Activities
- Has
@context - Has valid
type - Has
actoras URL - Has unique
id -
to/ccare arrays of URLs
For Create
- Has
object - Object has
id - Object has
type - Object has
attributedTo -
attributedTomatchesactor
For Follow
- Has
object(target actor URL) - Object is a valid actor URL
For Undo
- Has
object(activity being undone) - Actor matches original activity actor
Testing Tools
curl
# Test your activity endpoint
curl -X POST https://example.com/inbox \
-H "Content-Type: application/activity+json" \
-d '{
"@context": "https://www.w3.org/ns/activitystreams",
"type": "Create",
"actor": "https://example.com/users/alice",
"object": {
"type": "Note",
"content": "Test"
}
}'
Postman/Insomnia
Import ActivityPub collections for testing.
See Also
- Actor Inspector - Inspect remote actors
- WebFinger Lookup - Test discovery
- Test Suites - Comprehensive testing